mb-discid 0.1.4-x86-mswin32-60
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.
- data/CHANGES +29 -0
- data/LICENSE +25 -0
- data/README +54 -0
- data/Rakefile +137 -0
- data/examples/discid.rb +57 -0
- data/ext/MB_DiscID.so +0 -0
- data/ext/extconf.rb +13 -0
- data/ext/mb_discid.c +360 -0
- data/lib/mb-discid.rb +229 -0
- data/test/test_discid.rb +173 -0
- metadata +67 -0
data/CHANGES
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
= Changelog
|
2
|
+
|
3
|
+
== 0.1.4 (2009-11-19)
|
4
|
+
* Fixed calling +read+ method without argument
|
5
|
+
|
6
|
+
== 0.1.3 (2009-11-19)
|
7
|
+
* Added singleton method +sectors_to_seconds+ to convert sectors into seconds
|
8
|
+
* Added method +seconds+ to retrieve disc length in seconds
|
9
|
+
* Added method +track_info+ for accessing more detailed information about tracks
|
10
|
+
* Fixed building with Ruby 1.9 (Mihaly Csomay)
|
11
|
+
|
12
|
+
== 0.1.2 (2007-07-04)
|
13
|
+
* Support the method +put+ to set the TOC information directly instead of
|
14
|
+
reading it from a device.
|
15
|
+
* Fixed possible core dump if +read+ was called twice and failed the
|
16
|
+
second time.
|
17
|
+
* New to_s method (returns string representation of the ID itself).
|
18
|
+
* Complete RDoc documentation.
|
19
|
+
|
20
|
+
== 0.1.1 (2007-06-03)
|
21
|
+
* Minor changes to source to support MS compiler
|
22
|
+
* Provide Win32 binary gem
|
23
|
+
* Changed require of library to "require 'mb-discid'" (was "require 'DiscID'"
|
24
|
+
before, which was likely to cause problems)
|
25
|
+
|
26
|
+
== 0.1.0 (2007-06-02)
|
27
|
+
* Initial release
|
28
|
+
|
29
|
+
$Id: CHANGES 301 2009-11-19 11:39:31Z phw $
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2007, Philipp Wolfer
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
3. Neither the name of the RBrainz project nor the names of the
|
12
|
+
contributors may be used to endorse or promote products derived from
|
13
|
+
this software without specific prior written permission.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
16
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
17
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
18
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
19
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
20
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
21
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
22
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= MB-DiscID - Ruby bindings for MusicBrainz libdiscid
|
2
|
+
|
3
|
+
== About
|
4
|
+
MB-DiscID provides Ruby bindings for the MusicBrainz DiscID library libdiscid.
|
5
|
+
It allows you to calculate MusicBrainz DiscIDs from audio CDs which you can use
|
6
|
+
to find the release entry for your CD in the MusicBrainz database.
|
7
|
+
|
8
|
+
== Requirements
|
9
|
+
* Ruby >= 1.8.6
|
10
|
+
* libdiscid >= 0.1.0
|
11
|
+
|
12
|
+
== Installation
|
13
|
+
Before installing rdiscid make sure you have libdiscid installed. See
|
14
|
+
http://musicbrainz.org/doc/libdiscid for more information on how to do this.
|
15
|
+
|
16
|
+
=== Installation with RubyGems
|
17
|
+
gem install mb-discid
|
18
|
+
|
19
|
+
=== Installation on Windows operating systems.
|
20
|
+
For Windows a binary gem <tt>mb-discid-x.x.x-mswin32.gem</tt> is available. To
|
21
|
+
install it follow the instructions below:
|
22
|
+
|
23
|
+
1. Make sure you have at least Ruby 1.8.6 installed.
|
24
|
+
2. Install RubyGems, if you don't already have it.
|
25
|
+
3. Download <tt>libdiscid-0.1.1-win32bin.zip</tt> from
|
26
|
+
http://musicbrainz.org/doc/libdiscid.
|
27
|
+
4. Copy the file <tt>discid.dll</tt> from <tt>libdiscid-0.1.1-win32bin.zip</tt>
|
28
|
+
to your Ruby bin directory (normally <tt>C:\ruby\bin</tt>).
|
29
|
+
5. Run <tt>gem install mb-discid</tt> to install MB-DiscID.
|
30
|
+
6. To test the installation try to run <tt>examples/discid.rb</tt>.
|
31
|
+
|
32
|
+
=== Installing from source
|
33
|
+
rake install
|
34
|
+
|
35
|
+
== Usage
|
36
|
+
See the documentation of MusicBrainz::DiscID or the example files in the
|
37
|
+
+examples+ directory for usage information.
|
38
|
+
|
39
|
+
== Contact
|
40
|
+
MB-DiscID is part of the RBrainz project which provides a library to query
|
41
|
+
the MusicBrainz XML web service. For more information about MB-DiscID or
|
42
|
+
RBrainz visit http://rbrainz.rubyforge.org.
|
43
|
+
|
44
|
+
If you have any questions or suggestions regarding MB-DiscID please write to
|
45
|
+
the rbrainz-user mailinglist[http://rubyforge.org/mail/?group_id=3677].
|
46
|
+
If you find bugs or if you have any feature requests please use the
|
47
|
+
RBrainz bug tracker[http://rubyforge.org/tracker/?group_id=3677].
|
48
|
+
|
49
|
+
== License
|
50
|
+
MB-DiscID is Copyright (c) 2007 Philipp Wolfer.
|
51
|
+
It is free softare distributed under a BSD style license. See
|
52
|
+
LICENSE[link:files/LICENSE.html] for details.
|
53
|
+
|
54
|
+
$Id: README 298 2009-11-19 09:26:45Z phw $
|
data/Rakefile
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# $Id: Rakefile 300 2009-11-19 11:31:42Z phw $
|
2
|
+
# Copyright (c) 2007, Philipp Wolfer
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE for permissions.
|
5
|
+
|
6
|
+
# Rakefile for RDiscID
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require 'rake/testtask'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
|
13
|
+
task :default do
|
14
|
+
puts "Please see 'rake --tasks' for an overview of the available tasks."
|
15
|
+
end
|
16
|
+
|
17
|
+
# Packaging tasks: -------------------------------------------------------
|
18
|
+
|
19
|
+
PKG_NAME = 'mb-discid'
|
20
|
+
PKG_VERSION = '0.1.4'
|
21
|
+
PKG_SUMMARY = 'Ruby bindings for libdiscid.'
|
22
|
+
PKG_AUTHOR = 'Philipp Wolfer'
|
23
|
+
PKG_EMAIL = 'phw@rubyforge.org'
|
24
|
+
PKG_HOMEPAGE = 'http://rbrainz.rubyforge.org'
|
25
|
+
PKG_DESCRIPTION = <<EOF
|
26
|
+
Ruby bindings for libdiscid. See http://musicbrainz.org/doc/libdiscid
|
27
|
+
for more information on libdiscid and MusicBrainz.
|
28
|
+
EOF
|
29
|
+
PKG_FILES = FileList[
|
30
|
+
'Rakefile', 'LICENSE', 'README', 'CHANGES',
|
31
|
+
'examples/**/*.rb',
|
32
|
+
'ext/**/*.{c,rb}',
|
33
|
+
'lib/**/*.rb',
|
34
|
+
'test/**/*.rb'
|
35
|
+
]
|
36
|
+
PKG_EXTRA_RDOC_FILES = ['README', 'LICENSE', 'CHANGES']
|
37
|
+
|
38
|
+
spec = Gem::Specification.new do |spec|
|
39
|
+
spec.name = PKG_NAME
|
40
|
+
spec.version = PKG_VERSION
|
41
|
+
spec.summary = PKG_SUMMARY
|
42
|
+
if ENV['BINARY_GEM']
|
43
|
+
spec.platform = Gem::Platform::CURRENT
|
44
|
+
spec.files = PKG_FILES << 'ext/MB_DiscID.so'
|
45
|
+
spec.bindir = 'bin'
|
46
|
+
spec.required_ruby_version = ">= #{RUBY_VERSION}"
|
47
|
+
else
|
48
|
+
spec.platform = Gem::Platform::RUBY
|
49
|
+
spec.files = PKG_FILES
|
50
|
+
spec.extensions << 'ext/extconf.rb'
|
51
|
+
spec.required_ruby_version = ">= 1.8.6"
|
52
|
+
end
|
53
|
+
spec.requirements << 'libdiscid (http://musicbrainz.org/doc/libdiscid)'
|
54
|
+
spec.require_paths = ['lib', 'ext']
|
55
|
+
spec.autorequire = spec.name
|
56
|
+
spec.description = PKG_DESCRIPTION
|
57
|
+
spec.author = PKG_AUTHOR
|
58
|
+
spec.email = PKG_EMAIL
|
59
|
+
spec.homepage = PKG_HOMEPAGE
|
60
|
+
spec.rubyforge_project = 'rbrainz'
|
61
|
+
spec.has_rdoc = true
|
62
|
+
spec.extra_rdoc_files = PKG_EXTRA_RDOC_FILES
|
63
|
+
end
|
64
|
+
|
65
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
66
|
+
pkg.need_zip = true
|
67
|
+
pkg.need_tar_gz= true
|
68
|
+
end
|
69
|
+
|
70
|
+
# Build tasks: -----------------------------------------------------------
|
71
|
+
|
72
|
+
desc 'Build all the extensions'
|
73
|
+
task :build do
|
74
|
+
extconf_args = ''
|
75
|
+
|
76
|
+
unless ENV['DISCID_DIR'].nil?
|
77
|
+
extconf_args = "--with-discid-dir=#{ENV['DISCID_DIR']}"
|
78
|
+
end
|
79
|
+
|
80
|
+
cd 'ext' do
|
81
|
+
unless system("ruby extconf.rb #{extconf_args}")
|
82
|
+
STDERR.puts "ERROR: could not configure extension!\n" +
|
83
|
+
"\n#{INFO_NOTE}\n"
|
84
|
+
break
|
85
|
+
end
|
86
|
+
|
87
|
+
unless system('make') or system('nmake')
|
88
|
+
STDERR.puts 'ERROR: could not build extension!'
|
89
|
+
break
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
desc 'Install (and build) extensions'
|
95
|
+
task :install => [:build] do
|
96
|
+
cd 'ext' do
|
97
|
+
unless system('make install')
|
98
|
+
STDERR.puts 'ERROR: could not install extension!'
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'Remove extension products'
|
105
|
+
task :clobber_build do
|
106
|
+
FileList['ext/**/*'].each do |file|
|
107
|
+
unless FileList['ext/**/*.{c,rb}'].include?(file)
|
108
|
+
rm_r file if File.exists?(file)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
desc 'Force a rebuild of the extension files'
|
114
|
+
task :rebuild => [:clobber_build, :build]
|
115
|
+
|
116
|
+
desc 'Remove all files created during the build process'
|
117
|
+
task :clobber => [:clobber_build, :clobber_package]
|
118
|
+
|
119
|
+
# Test tasks: ------------------------------------------------------------
|
120
|
+
|
121
|
+
desc "Run just the unit tests"
|
122
|
+
Rake::TestTask.new(:test => [:rebuild]) do |test|
|
123
|
+
test.test_files = FileList['test/test*.rb']
|
124
|
+
test.libs = ['lib', 'ext']
|
125
|
+
test.warning = true
|
126
|
+
end
|
127
|
+
|
128
|
+
# Documentation tasks: ---------------------------------------------------
|
129
|
+
|
130
|
+
Rake::RDocTask.new do |rdoc|
|
131
|
+
rdoc.title = "MB-DiscID %s" % PKG_VERSION
|
132
|
+
rdoc.main = 'README'
|
133
|
+
rdoc.rdoc_dir = 'doc/api'
|
134
|
+
rdoc.rdoc_files.include('ext/**/*.c', 'lib/**/*.rb', PKG_EXTRA_RDOC_FILES)
|
135
|
+
rdoc.options << '--inline-source' << '--line-numbers' #<< '--diagram'
|
136
|
+
end
|
137
|
+
|
data/examples/discid.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Example script for MB-DiscID.
|
4
|
+
#
|
5
|
+
# This script will read the disc ID from the default device and print
|
6
|
+
# the results. You can specify an alternate device to use by giving the
|
7
|
+
# device's name as the first command line argument.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# ./discid.rb /dev/dvd
|
11
|
+
#
|
12
|
+
# $Id: discid.rb 201 2008-02-13 14:59:48Z phw $
|
13
|
+
|
14
|
+
require 'mb-discid'
|
15
|
+
|
16
|
+
# Read the device name from the command line or use the default.
|
17
|
+
device = $*[0] ? $*[0] : MusicBrainz::DiscID.default_device
|
18
|
+
|
19
|
+
# Create a new DiscID object and read the disc information.
|
20
|
+
# In case of errors exit the application.
|
21
|
+
puts "Reading TOC from device '#{device}'."
|
22
|
+
begin
|
23
|
+
disc = MusicBrainz::DiscID.new
|
24
|
+
disc.read(device)
|
25
|
+
|
26
|
+
# Instead of reading from a device we could set the TOC directly:
|
27
|
+
# disc.put(1, 82255, [150, 16157, 35932, 57527])
|
28
|
+
rescue Exception => e
|
29
|
+
puts e
|
30
|
+
exit(1)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Print information about the disc:
|
34
|
+
print <<EOF
|
35
|
+
|
36
|
+
DiscID : #{disc.id}
|
37
|
+
FreeDB ID : #{disc.freedb_id}
|
38
|
+
First track : #{disc.first_track_num}
|
39
|
+
Last track : #{disc.last_track_num}
|
40
|
+
Total length: #{disc.seconds} seconds
|
41
|
+
Sectors : #{disc.sectors}
|
42
|
+
EOF
|
43
|
+
|
44
|
+
# Print information about individual tracks:
|
45
|
+
disc.track_details do |track_info|
|
46
|
+
puts "Track ##{track_info.number}"
|
47
|
+
puts " Length: %02d:%02d (%i sectors)" %
|
48
|
+
[track_info.seconds / 60, track_info.seconds % 60, track_info.sectors]
|
49
|
+
puts " Start : %02d:%02d (sector %i)" %
|
50
|
+
[track_info.start_time / 60, track_info.start_time % 60, track_info.start_sector]
|
51
|
+
puts " End : %02d:%02d (sector %i)" %
|
52
|
+
[track_info.end_time / 60, track_info.end_time % 60, track_info.end_sector]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Print a submission URL that can be used to submit
|
56
|
+
# the disc ID to MusicBrainz.org.
|
57
|
+
puts "\nSubmit via #{disc.submission_url}"
|
data/ext/MB_DiscID.so
ADDED
Binary file
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# $Id: extconf.rb 68 2007-06-03 14:12:21Z phw $
|
3
|
+
|
4
|
+
require 'mkmf'
|
5
|
+
|
6
|
+
if have_library('discid', 'discid_new') or
|
7
|
+
have_library('discid.dll', 'discid_new')
|
8
|
+
# Remove -MD from compiler flags on Windows.
|
9
|
+
$CFLAGS.sub!('-MD', '') if RUBY_PLATFORM.include? 'win32'
|
10
|
+
create_makefile('MB_DiscID')
|
11
|
+
else
|
12
|
+
puts 'Required library libdiscid not found.'
|
13
|
+
end
|
data/ext/mb_discid.c
ADDED
@@ -0,0 +1,360 @@
|
|
1
|
+
/**
|
2
|
+
* $Id: mb_discid.c 301 2009-11-19 11:39:31Z phw $
|
3
|
+
*
|
4
|
+
* Ruby bindings for libdiscid. See http://musicbrainz.org/doc/libdiscid
|
5
|
+
* for more information on libdiscid and MusicBrainz.
|
6
|
+
*
|
7
|
+
* Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
|
8
|
+
* Copyright:: Copyright (c) 2007, Philipp Wolfer
|
9
|
+
* License:: MB-DiscID is free software distributed under a BSD style license.
|
10
|
+
* See LICENSE for permissions.
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include "ruby.h"
|
14
|
+
#include "discid/discid.h"
|
15
|
+
|
16
|
+
/**
|
17
|
+
* The MusicBrainz module.
|
18
|
+
*/
|
19
|
+
static VALUE mMusicBrainz;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* The DiscID class.
|
23
|
+
*/
|
24
|
+
static VALUE cDiscID;
|
25
|
+
|
26
|
+
/**
|
27
|
+
* call-seq:
|
28
|
+
* id() -> string or nil
|
29
|
+
*
|
30
|
+
* Returns the DiscID as a string.
|
31
|
+
*
|
32
|
+
* Returns +nil+ if no ID was yet read.
|
33
|
+
*/
|
34
|
+
static VALUE mb_discid_id(VALUE self)
|
35
|
+
{
|
36
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
37
|
+
return Qnil;
|
38
|
+
else
|
39
|
+
{
|
40
|
+
DiscId *disc;
|
41
|
+
Data_Get_Struct(self, DiscId, disc);
|
42
|
+
|
43
|
+
return rb_str_new2(discid_get_id(disc));
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* call-seq:
|
49
|
+
* submission_url() -> string or nil
|
50
|
+
*
|
51
|
+
* Returns a submission URL for the DiscID as a string.
|
52
|
+
*
|
53
|
+
* Returns +nil+ if no ID was yet read.
|
54
|
+
*/
|
55
|
+
static VALUE mb_discid_submission_url(VALUE self)
|
56
|
+
{
|
57
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
58
|
+
return Qnil;
|
59
|
+
else
|
60
|
+
{
|
61
|
+
DiscId *disc;
|
62
|
+
Data_Get_Struct(self, DiscId, disc);
|
63
|
+
|
64
|
+
return rb_str_new2(discid_get_submission_url(disc));
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* call-seq:
|
70
|
+
* freedb_id() -> string or nil
|
71
|
+
*
|
72
|
+
* Returns a FreeDB DiscID as a string.
|
73
|
+
*
|
74
|
+
* Returns +nil+ if no ID was yet read.
|
75
|
+
*/
|
76
|
+
static VALUE mb_discid_freedb_id(VALUE self)
|
77
|
+
{
|
78
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
79
|
+
return Qnil;
|
80
|
+
else
|
81
|
+
{
|
82
|
+
DiscId *disc;
|
83
|
+
Data_Get_Struct(self, DiscId, disc);
|
84
|
+
|
85
|
+
return rb_str_new2(discid_get_freedb_id(disc));
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* call-seq:
|
91
|
+
* first_track_num() -> int or nil
|
92
|
+
*
|
93
|
+
* Return the number of the first track on this disc (usually 1).
|
94
|
+
*
|
95
|
+
* Returns +nil+ if no ID was yet read.
|
96
|
+
*/
|
97
|
+
static VALUE mb_discid_first_track_num(VALUE self)
|
98
|
+
{
|
99
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
100
|
+
return Qnil;
|
101
|
+
else
|
102
|
+
{
|
103
|
+
DiscId *disc;
|
104
|
+
Data_Get_Struct(self, DiscId, disc);
|
105
|
+
|
106
|
+
return INT2FIX(discid_get_first_track_num(disc));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
/**
|
111
|
+
* call-seq:
|
112
|
+
* last_track_num() -> int or nil
|
113
|
+
*
|
114
|
+
* Return the number of the last track on this disc.
|
115
|
+
*
|
116
|
+
* Returns +nil+ if no ID was yet read.
|
117
|
+
*/
|
118
|
+
static VALUE mb_discid_last_track_num(VALUE self)
|
119
|
+
{
|
120
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
121
|
+
return Qnil;
|
122
|
+
else
|
123
|
+
{
|
124
|
+
DiscId *disc;
|
125
|
+
Data_Get_Struct(self, DiscId, disc);
|
126
|
+
|
127
|
+
return INT2FIX(discid_get_last_track_num(disc));
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* call-seq:
|
133
|
+
* sectors() -> int or nil
|
134
|
+
*
|
135
|
+
* Return the length of the disc in sectors.
|
136
|
+
*
|
137
|
+
* Returns +nil+ if no ID was yet read.
|
138
|
+
*/
|
139
|
+
static VALUE mb_discid_sectors(VALUE self)
|
140
|
+
{
|
141
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
142
|
+
return Qnil;
|
143
|
+
else
|
144
|
+
{
|
145
|
+
DiscId *disc;
|
146
|
+
Data_Get_Struct(self, DiscId, disc);
|
147
|
+
|
148
|
+
return INT2FIX(discid_get_sectors(disc));
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* call-seq:
|
154
|
+
* tracks() -> array
|
155
|
+
* tracks() {|offset, length| block }
|
156
|
+
*
|
157
|
+
* Returns an array of <tt>[offset, length]</tt> tuples for each track.
|
158
|
+
*
|
159
|
+
* Offset and length are both integer values representing sectors.
|
160
|
+
* If a block is given this method returns +nil+ and instead iterates over the
|
161
|
+
* block calling the block with two arguments <tt>|offset, length|</tt>.
|
162
|
+
*
|
163
|
+
* Returns always +nil+ if no ID was yet read. The block won't be called in
|
164
|
+
* this case.
|
165
|
+
*
|
166
|
+
* You may want to use the method track_details instead of this method to
|
167
|
+
* retrieve more detailed information about the tracks.
|
168
|
+
*/
|
169
|
+
static VALUE mb_discid_tracks(VALUE self)
|
170
|
+
{
|
171
|
+
if (rb_iv_get(self, "@read") == Qfalse)
|
172
|
+
return Qnil;
|
173
|
+
else
|
174
|
+
{
|
175
|
+
DiscId *disc; /* Pointer to the disc struct */
|
176
|
+
VALUE result = rb_ary_new(); /* Array of all [offset, length] tuples */
|
177
|
+
VALUE tuple; /* Array to store one [offset, length] tuple. */
|
178
|
+
int track; /* Counter for the track number to process. */
|
179
|
+
|
180
|
+
Data_Get_Struct(self, DiscId, disc);
|
181
|
+
|
182
|
+
track = discid_get_first_track_num(disc); /* First track number */
|
183
|
+
while (track <= discid_get_last_track_num(disc))
|
184
|
+
{
|
185
|
+
tuple = rb_ary_new3(2,
|
186
|
+
INT2FIX(discid_get_track_offset(disc, track)),
|
187
|
+
INT2FIX(discid_get_track_length(disc, track)) );
|
188
|
+
|
189
|
+
if (rb_block_given_p())
|
190
|
+
rb_yield(tuple);
|
191
|
+
else
|
192
|
+
rb_ary_push(result, tuple);
|
193
|
+
|
194
|
+
track++;
|
195
|
+
}
|
196
|
+
|
197
|
+
if (rb_block_given_p())
|
198
|
+
return Qnil;
|
199
|
+
else
|
200
|
+
return result;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
/**
|
205
|
+
* call-seq:
|
206
|
+
* read(device=nil)
|
207
|
+
*
|
208
|
+
* Read the disc ID from the given device.
|
209
|
+
*
|
210
|
+
* If no device is given the default device of the platform will be used.
|
211
|
+
* Throws an _Exception_ if the CD's TOC can not be read.
|
212
|
+
*
|
213
|
+
* Raises:: ArgumentError, TypeError, Exception
|
214
|
+
*/
|
215
|
+
static VALUE mb_discid_read(int argc, VALUE *argv, VALUE self)
|
216
|
+
{
|
217
|
+
DiscId *disc; /* Pointer to the disc struct */
|
218
|
+
VALUE device = Qnil; /* The device string as a Ruby string */
|
219
|
+
char* cdevice; /* The device string as a C string */
|
220
|
+
|
221
|
+
Data_Get_Struct(self, DiscId, disc);
|
222
|
+
|
223
|
+
/* Check the number and types of arguments */
|
224
|
+
rb_scan_args(argc, argv, "01", &device);
|
225
|
+
|
226
|
+
/* Use the default device if none was given. */
|
227
|
+
if (device == Qnil)
|
228
|
+
cdevice = discid_get_default_device();
|
229
|
+
else if (rb_respond_to(device, rb_intern("to_s")))
|
230
|
+
{
|
231
|
+
device = rb_funcall(device, rb_intern("to_s"), 0, 0);
|
232
|
+
cdevice = StringValuePtr(device);
|
233
|
+
}
|
234
|
+
else
|
235
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected String)");
|
236
|
+
|
237
|
+
/* Mark the disc id as unread in case something goes wrong. */
|
238
|
+
rb_iv_set(self, "@read", Qfalse);
|
239
|
+
|
240
|
+
/* Read the discid */
|
241
|
+
if (discid_read(disc, cdevice) == 0)
|
242
|
+
rb_raise(rb_eException, discid_get_error_msg(disc));
|
243
|
+
else /* Remember that we already read the ID. */
|
244
|
+
rb_iv_set(self, "@read", Qtrue);
|
245
|
+
|
246
|
+
return Qnil;
|
247
|
+
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* call-seq:
|
252
|
+
* put(first_track, sectors, offsets)
|
253
|
+
*
|
254
|
+
* Set the TOC information directly instead of reading it from a device.
|
255
|
+
*
|
256
|
+
* Use this instead of read if the TOC information was already read elsewhere
|
257
|
+
* and you want to recalculate the ID.
|
258
|
+
* Throws an _Exception_ if the CD's TOC can not be read.
|
259
|
+
*
|
260
|
+
* <b>Parameters:</b>
|
261
|
+
* [first_track] The number of the first track on the disc (usually 1).
|
262
|
+
* [sectors] The total number of sectors on the disc.
|
263
|
+
* [offsets] Array of all track offsets. The number of tracks must not exceed 99.
|
264
|
+
*
|
265
|
+
* Raises:: Exception
|
266
|
+
*/
|
267
|
+
static VALUE mb_discid_put(VALUE self, VALUE first_track, VALUE sectors,
|
268
|
+
VALUE offsets)
|
269
|
+
{
|
270
|
+
DiscId *disc; /* Pointer to the disc struct */
|
271
|
+
long length = RARRAY_LEN(offsets); /* length of the offsets array */
|
272
|
+
int cfirst = NUM2INT(first_track); /* number of the first track */
|
273
|
+
int clast = length + 1 - cfirst; /* number of the last track */
|
274
|
+
int coffsets[100]; /* C array to hold the offsets */
|
275
|
+
int i = 1; /* Counter for iterating over coffsets*/
|
276
|
+
|
277
|
+
Data_Get_Struct(self, DiscId, disc);
|
278
|
+
|
279
|
+
/* Convert the Ruby array to an C array of integers. discid_puts expects
|
280
|
+
always an offsets array with exactly 100 elements. */
|
281
|
+
coffsets[0] = NUM2INT(sectors); /* 0 is always the leadout track */
|
282
|
+
while (i <= length && i < 100)
|
283
|
+
{
|
284
|
+
coffsets[i] = NUM2INT(rb_ary_entry(offsets, i - 1));
|
285
|
+
i++;
|
286
|
+
}
|
287
|
+
|
288
|
+
/* Mark the disc id as unread in case something goes wrong. */
|
289
|
+
rb_iv_set(self, "@read", Qfalse);
|
290
|
+
|
291
|
+
/* Read the discid */
|
292
|
+
if (discid_put(disc, cfirst, clast, coffsets) == 0)
|
293
|
+
rb_raise(rb_eException, discid_get_error_msg(disc));
|
294
|
+
else /* Remember that we already read the ID. */
|
295
|
+
rb_iv_set(self, "@read", Qtrue);
|
296
|
+
|
297
|
+
return Qnil;
|
298
|
+
}
|
299
|
+
|
300
|
+
/**
|
301
|
+
* call-seq:
|
302
|
+
* MusicBrainz::DiscID.new(device=nil) -> obj
|
303
|
+
*
|
304
|
+
* Construct a new DiscID object.
|
305
|
+
*
|
306
|
+
* As an optional argument the name of the device to read the ID from
|
307
|
+
* may be given. If you don't specify a device here you can later read
|
308
|
+
* the ID with the read method.
|
309
|
+
*
|
310
|
+
* Raises:: ArgumentError, TypeError, Exception
|
311
|
+
*/
|
312
|
+
VALUE mb_discid_new(int argc, VALUE *argv, VALUE class)
|
313
|
+
{
|
314
|
+
DiscId *disc = discid_new();
|
315
|
+
VALUE tdata = Data_Wrap_Struct(class, 0, discid_free, disc);
|
316
|
+
VALUE device = Qnil;
|
317
|
+
rb_obj_call_init(tdata, 0, 0);
|
318
|
+
rb_iv_set(tdata, "@read", Qfalse);
|
319
|
+
|
320
|
+
/* Check the number of arguments */
|
321
|
+
rb_scan_args(argc, argv, "01", &device);
|
322
|
+
|
323
|
+
if (device != Qnil)
|
324
|
+
rb_funcall(tdata, rb_intern("read"), 1, device);
|
325
|
+
|
326
|
+
return tdata;
|
327
|
+
}
|
328
|
+
|
329
|
+
/**
|
330
|
+
* call-seq:
|
331
|
+
* MusicBrainz::DiscID.default_device(device=nil) -> string
|
332
|
+
*
|
333
|
+
* Returns a device string for the default device for this platform.
|
334
|
+
*/
|
335
|
+
VALUE mb_discid_default_device(VALUE class)
|
336
|
+
{
|
337
|
+
return rb_str_new2(discid_get_default_device());
|
338
|
+
}
|
339
|
+
|
340
|
+
/**
|
341
|
+
* Initialize the DiscID class and make it available in Ruby.
|
342
|
+
*/
|
343
|
+
void Init_MB_DiscID()
|
344
|
+
{
|
345
|
+
mMusicBrainz = rb_define_module("MusicBrainz");
|
346
|
+
cDiscID = rb_define_class_under(mMusicBrainz, "DiscID", rb_cObject);
|
347
|
+
rb_define_singleton_method(cDiscID, "new", mb_discid_new, -1);
|
348
|
+
rb_define_singleton_method(cDiscID, "default_device",
|
349
|
+
mb_discid_default_device, 0);
|
350
|
+
|
351
|
+
rb_define_method(cDiscID, "read", mb_discid_read, -1);
|
352
|
+
rb_define_method(cDiscID, "put", mb_discid_put, 3);
|
353
|
+
rb_define_method(cDiscID, "id", mb_discid_id, 0);
|
354
|
+
rb_define_method(cDiscID, "submission_url", mb_discid_submission_url, 0);
|
355
|
+
rb_define_method(cDiscID, "freedb_id", mb_discid_freedb_id, 0);
|
356
|
+
rb_define_method(cDiscID, "first_track_num", mb_discid_first_track_num, 0);
|
357
|
+
rb_define_method(cDiscID, "last_track_num", mb_discid_last_track_num, 0);
|
358
|
+
rb_define_method(cDiscID, "sectors", mb_discid_sectors, 0);
|
359
|
+
rb_define_method(cDiscID, "tracks", mb_discid_tracks, 0);
|
360
|
+
}
|
data/lib/mb-discid.rb
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
# $Id: mb-discid.rb 201 2008-02-13 14:59:48Z phw $
|
2
|
+
#
|
3
|
+
# Just a helper file to allow loading the MB-DiscID library with
|
4
|
+
# <tt>require 'mb-discid'</tt>, which is the only recommended way
|
5
|
+
# to load the library.
|
6
|
+
#
|
7
|
+
# This file may even provide extensions to the library in the future
|
8
|
+
# to avoid to have to write everything in C.
|
9
|
+
#
|
10
|
+
# Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
|
11
|
+
# Copyright:: Copyright (c) 2007, Philipp Wolfer
|
12
|
+
# License:: MB-DiscID is free software distributed under a BSD style license.
|
13
|
+
# See LICENSE[file:../LICENSE.html] for permissions.
|
14
|
+
|
15
|
+
require 'MB_DiscID.so'
|
16
|
+
|
17
|
+
module MusicBrainz
|
18
|
+
|
19
|
+
# Class to calculate a MusicBrainz DiscID from an audio CD in the drive.
|
20
|
+
#
|
21
|
+
# This is basically an interface to the libdiscid C library
|
22
|
+
# (http://musicbrainz.org/doc/libdiscid).
|
23
|
+
#
|
24
|
+
# == Usage
|
25
|
+
# === Basic Usage:
|
26
|
+
#
|
27
|
+
# require 'mb-discid'
|
28
|
+
#
|
29
|
+
# # Create a new DiscID object.
|
30
|
+
# disc = MusicBrainz::DiscID.new
|
31
|
+
#
|
32
|
+
# # Read the TOC from the default device.
|
33
|
+
# # An audio CD must be inserted in the drive. An exception will be thrown
|
34
|
+
# # if the CD can't be read.
|
35
|
+
# begin
|
36
|
+
# disc.read
|
37
|
+
# rescue Exception => e
|
38
|
+
# puts e
|
39
|
+
# exit(1)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # Print information about the disc:
|
43
|
+
# print <<EOF
|
44
|
+
# DiscID : #{disc.id}
|
45
|
+
# Submit via : #{disc.submission_url}
|
46
|
+
# FreeDB ID : #{disc.freedb_id}
|
47
|
+
# First track : #{disc.first_track_num}
|
48
|
+
# Last track : #{disc.last_track_num}
|
49
|
+
# Total length: #{disc.seconds} seconds
|
50
|
+
# Sectors : #{disc.sectors}
|
51
|
+
# EOF
|
52
|
+
#
|
53
|
+
# # Print information about individual tracks:
|
54
|
+
# disc.track_details do |track_info|
|
55
|
+
# puts "Track ##{track_info.number}"
|
56
|
+
# puts " Length: %02d:%02d (%i sectors)" %
|
57
|
+
# [track_info.seconds / 60, track_info.seconds % 60, track_info.sectors]
|
58
|
+
# puts " Start : %02d:%02d (sector %i)" %
|
59
|
+
# [track_info.start_time / 60, track_info.start_time % 60, track_info.start_sector]
|
60
|
+
# puts " End : %02d:%02d (sector %i)" %
|
61
|
+
# [track_info.end_time / 60, track_info.end_time % 60, track_info.end_sector]
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# # Print a submission URL that can be used to submit
|
65
|
+
# # the disc ID to MusicBrainz.org.
|
66
|
+
# puts "\nSubmit via #{disc.submission_url}"
|
67
|
+
#
|
68
|
+
# === Specifying the device to read from:
|
69
|
+
#
|
70
|
+
# # Create a new DiscID object and read the disc in /dev/dvd:
|
71
|
+
# disc = MusicBrainz::DiscID.new
|
72
|
+
# disc.read('/dev/dvd')
|
73
|
+
#
|
74
|
+
# # Create a new DiscID object and directly read the disc in /dev/dvd:
|
75
|
+
# disc = MusicBrainz::DiscID.new('/dev/dvd')
|
76
|
+
#
|
77
|
+
# # Create a new DiscID object and directly read the disc in the platform's
|
78
|
+
# # default device:
|
79
|
+
# disc = MusicBrainz::DiscID.new(MusicBrainz::DiscID.default_device)
|
80
|
+
#
|
81
|
+
# === Calculating the DiscID for a given TOC
|
82
|
+
#
|
83
|
+
# disc = MusicBrainz::DiscID.new
|
84
|
+
#
|
85
|
+
# first_track = 1
|
86
|
+
# sectors = 224556
|
87
|
+
# track_offsets = [150, 9078, 13528, 34182, 53768, 70987, 96424,
|
88
|
+
# 118425, 136793, 159514, 179777, 198006]
|
89
|
+
#
|
90
|
+
# disc.put(first_track, sectors, track_offsets)
|
91
|
+
# puts disc.id # Should print "T_prJXQSrqbnH8OE.dgOKsHm5Uw-"
|
92
|
+
#
|
93
|
+
class DiscID
|
94
|
+
|
95
|
+
# This class holds information about a single track.
|
96
|
+
#
|
97
|
+
# Currently this includes the following fields:
|
98
|
+
# [number] The number of the track on the disc.
|
99
|
+
# [sectors] Length of the track in sectors.
|
100
|
+
# [start_sector] Start position of the track on the disc in sectors.
|
101
|
+
# [end_sector] End position of the track on the disc in sectors.
|
102
|
+
# [seconds] Length of the track in seconds.
|
103
|
+
# [start_time] Start position of the track on the disc in seconds.
|
104
|
+
# [end_time] End position of the track on the disc in seconds.
|
105
|
+
#
|
106
|
+
# You can access all fields either with directly or with the square bracket
|
107
|
+
# notation:
|
108
|
+
#
|
109
|
+
# track = TrackInfo.new(1, 150, 16007)
|
110
|
+
# puts track.sectors # 16007
|
111
|
+
# puts track[:sectors] # 16007
|
112
|
+
#
|
113
|
+
# See:: DiscID#track_details
|
114
|
+
class TrackInfo
|
115
|
+
|
116
|
+
# The number of the track on the disc.
|
117
|
+
attr_reader :number
|
118
|
+
|
119
|
+
# Length of the track in sectors.
|
120
|
+
attr_reader :sectors
|
121
|
+
|
122
|
+
# Start position of the track on the disc in sectors.
|
123
|
+
attr_reader :start_sector
|
124
|
+
|
125
|
+
# Returns a new TrackInfo.
|
126
|
+
def initialize(number, offset, length)
|
127
|
+
@number = number
|
128
|
+
@start_sector = offset
|
129
|
+
@sectors = length
|
130
|
+
end
|
131
|
+
|
132
|
+
# End position of the track on the disc in sectors.
|
133
|
+
def end_sector
|
134
|
+
start_sector + sectors
|
135
|
+
end
|
136
|
+
|
137
|
+
# Length of the track in seconds.
|
138
|
+
def seconds
|
139
|
+
DiscID.sectors_to_seconds(sectors)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Start position of the track on the disc in seconds.
|
143
|
+
def start_time
|
144
|
+
DiscID.sectors_to_seconds(start_sector)
|
145
|
+
end
|
146
|
+
|
147
|
+
# End position of the track on the disc in seconds.
|
148
|
+
def end_time
|
149
|
+
DiscID.sectors_to_seconds(end_sector)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Allows access to all fields similar to accessing values in a hash.
|
153
|
+
#
|
154
|
+
# Example:
|
155
|
+
# track = TrackInfo.new(1, 150, 16007)
|
156
|
+
# puts track.sectors # 16007
|
157
|
+
# puts track[:sectors] # 16007
|
158
|
+
def [](key)
|
159
|
+
if [:number, :sectors, :start_sector, :end_sector,
|
160
|
+
:seconds, :start_time, :end_time].include?(key.to_sym)
|
161
|
+
method(key).call
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Converts the TrackInfo into a Hash.
|
166
|
+
def to_hash
|
167
|
+
{
|
168
|
+
:sectors => sectors,
|
169
|
+
:start_sector => start_sector,
|
170
|
+
:end_sector => end_sector,
|
171
|
+
:seconds => seconds,
|
172
|
+
:start_time => start_time,
|
173
|
+
:end_time => end_time,
|
174
|
+
}
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
# DiscID to String conversion. Same as calling the method id but guaranteed
|
180
|
+
# to return a string.
|
181
|
+
def to_s
|
182
|
+
id.to_s
|
183
|
+
end
|
184
|
+
|
185
|
+
# Return the length of the disc in sectors.
|
186
|
+
#
|
187
|
+
# Returns <tt>nil</tt> if no ID was yet read.
|
188
|
+
def seconds
|
189
|
+
DiscID.sectors_to_seconds(sectors) unless @read == false
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns an array of TrackInfo objects. Each TrackInfo object contains
|
193
|
+
# detailed information about the track.
|
194
|
+
#
|
195
|
+
# If a block is given this method returns <tt>nil</tt> and instead iterates
|
196
|
+
# over the block calling the block with one argument <tt>|track_info|</tt>.
|
197
|
+
#
|
198
|
+
# Returns always <tt>nil</tt> if no ID was yet read. The block won't be
|
199
|
+
# called in this case.
|
200
|
+
def track_details
|
201
|
+
unless @read == false
|
202
|
+
track_number = self.first_track_num - 1
|
203
|
+
tracks = []
|
204
|
+
|
205
|
+
self.tracks do |offset, length|
|
206
|
+
track_number += 1
|
207
|
+
track_info = TrackInfo.new(track_number, offset, length)
|
208
|
+
|
209
|
+
if block_given?
|
210
|
+
yield track_info
|
211
|
+
else
|
212
|
+
tracks << track_info
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
return tracks unless block_given?
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Converts sectors to seconds.
|
221
|
+
#
|
222
|
+
# According to the red book standard 75 sectors are one second.
|
223
|
+
def self.sectors_to_seconds(sectors)
|
224
|
+
return (sectors.to_f / 75).round
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
data/test/test_discid.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# $Id: test_discid.rb 236 2009-05-07 05:58:07Z phw $
|
2
|
+
#
|
3
|
+
# Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
|
4
|
+
# Copyright:: Copyright (c) 2007, Philipp Wolfer
|
5
|
+
# License:: RBrainz is free software distributed under a BSD style license.
|
6
|
+
# See LICENSE[file:../LICENSE.html] for permissions.
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
require 'mb-discid'
|
10
|
+
|
11
|
+
# Helper class which can't be converted into a string.
|
12
|
+
class NotAString
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# Unit test for the MusicBrainz::DiscID class.
|
22
|
+
class TestDiscID < Test::Unit::TestCase
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@fiction_disc_id = 'Wn8eRBtfLDfM0qjYPdxrz.Zjs_U-'
|
26
|
+
@fiction_first_track = 1
|
27
|
+
@fiction_last_track = 10
|
28
|
+
@fiction_sectors = 206535
|
29
|
+
@fiction_seconds = 2754
|
30
|
+
@fiction_offsets = [150, 18901, 39738, 59557, 79152, 100126,
|
31
|
+
124833, 147278, 166336, 182560]
|
32
|
+
@fiction_lengths = [18751, 20837, 19819, 19595, 20974,
|
33
|
+
24707, 22445, 19058, 16224, 23975]
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
end
|
38
|
+
|
39
|
+
# Test reading the disc id from a device.
|
40
|
+
# We would need some kind of small test data to do this.
|
41
|
+
#def test_read
|
42
|
+
# assert false, "Not implemented yet"
|
43
|
+
#end
|
44
|
+
|
45
|
+
# Test how read reacts on different arguments.
|
46
|
+
# Those reads should all fail, but they must never cause a segmentation fault.
|
47
|
+
def test_read_invalid_arguments
|
48
|
+
assert_raise(TypeError) {MusicBrainz::DiscID.new(NotAString.new)}
|
49
|
+
assert_raise(Exception) {MusicBrainz::DiscID.new(1)}
|
50
|
+
assert_raise(Exception) {MusicBrainz::DiscID.new('invalid_device')}
|
51
|
+
assert_raise(Exception) {MusicBrainz::DiscID.new(:invalid_device)}
|
52
|
+
assert_raise(ArgumentError) {MusicBrainz::DiscID.new(
|
53
|
+
MusicBrainz::DiscID.default_device,
|
54
|
+
'second argument')}
|
55
|
+
|
56
|
+
disc = MusicBrainz::DiscID.new
|
57
|
+
assert_raise(TypeError) {disc.read(NotAString.new)}
|
58
|
+
assert_raise(Exception) {disc.read(1)}
|
59
|
+
assert_raise(Exception) {disc.read('invalid_device')}
|
60
|
+
assert_raise(Exception) {disc.read(:invalid_device)}
|
61
|
+
assert_raise(ArgumentError) {disc.read(MusicBrainz::DiscID.default_device,
|
62
|
+
'second argument')}
|
63
|
+
end
|
64
|
+
|
65
|
+
# Test calculation of the disc id if the TOC information
|
66
|
+
# gets set by the put method.
|
67
|
+
# All attributes should be nil after a failure, even if there was a
|
68
|
+
# successfull put before.
|
69
|
+
def test_put
|
70
|
+
disc = MusicBrainz::DiscID.new
|
71
|
+
assert_equal nil, disc.id
|
72
|
+
assert_equal '', disc.to_s
|
73
|
+
assert_equal nil, disc.first_track_num
|
74
|
+
assert_equal nil, disc.last_track_num
|
75
|
+
assert_equal nil, disc.sectors
|
76
|
+
assert_equal nil, disc.seconds
|
77
|
+
assert_equal nil, disc.tracks
|
78
|
+
|
79
|
+
# First erroneous put
|
80
|
+
assert_raise(Exception) {disc.put(-1, @fiction_sectors, @fiction_offsets)}
|
81
|
+
assert_equal nil, disc.id
|
82
|
+
assert_equal '', disc.to_s
|
83
|
+
assert_equal nil, disc.first_track_num
|
84
|
+
assert_equal nil, disc.last_track_num
|
85
|
+
assert_equal nil, disc.sectors
|
86
|
+
assert_equal nil, disc.seconds
|
87
|
+
assert_equal nil, disc.tracks
|
88
|
+
|
89
|
+
# Second successfull put
|
90
|
+
assert_nothing_raised {disc.put(@fiction_first_track, @fiction_sectors,
|
91
|
+
@fiction_offsets)}
|
92
|
+
assert_equal @fiction_disc_id, disc.id
|
93
|
+
assert_equal @fiction_disc_id, disc.to_s
|
94
|
+
assert_equal @fiction_first_track, disc.first_track_num
|
95
|
+
assert_equal @fiction_last_track, disc.last_track_num
|
96
|
+
assert_equal @fiction_sectors, disc.sectors
|
97
|
+
assert_equal @fiction_seconds, disc.seconds
|
98
|
+
assert_equal @fiction_offsets, disc.tracks.map{|t| t[0]}
|
99
|
+
assert_equal @fiction_lengths, disc.tracks.map{|t| t[1]}
|
100
|
+
|
101
|
+
# Third erroneous put
|
102
|
+
assert_raise(Exception) {disc.put(@fiction_first_track, @fiction_sectors,
|
103
|
+
Array.new(100, 1))}
|
104
|
+
assert_equal nil, disc.id
|
105
|
+
assert_equal '', disc.to_s
|
106
|
+
assert_equal nil, disc.first_track_num
|
107
|
+
assert_equal nil, disc.last_track_num
|
108
|
+
assert_equal nil, disc.sectors
|
109
|
+
assert_equal nil, disc.seconds
|
110
|
+
assert_equal nil, disc.tracks
|
111
|
+
end
|
112
|
+
|
113
|
+
# Test the track info method and TrackInfo objects
|
114
|
+
def test_track_details
|
115
|
+
disc = MusicBrainz::DiscID.new
|
116
|
+
|
117
|
+
assert_equal nil, disc.track_details
|
118
|
+
assert_nothing_raised {disc.put(@fiction_first_track, @fiction_sectors,
|
119
|
+
@fiction_offsets)}
|
120
|
+
|
121
|
+
|
122
|
+
# Save a block for testing each track
|
123
|
+
number = 0
|
124
|
+
proc_test_track = lambda do |track|
|
125
|
+
assert_equal number + 1, track.number
|
126
|
+
|
127
|
+
assert_equal @fiction_offsets[number], track.start_sector
|
128
|
+
assert_equal @fiction_lengths[number], track.sectors
|
129
|
+
assert_equal @fiction_offsets[number]+ @fiction_lengths[number],
|
130
|
+
track.end_sector
|
131
|
+
|
132
|
+
assert_equal MusicBrainz::DiscID.sectors_to_seconds(@fiction_offsets[number]),
|
133
|
+
track.start_time
|
134
|
+
assert_equal MusicBrainz::DiscID.sectors_to_seconds(@fiction_lengths[number]),
|
135
|
+
track.seconds
|
136
|
+
assert_equal MusicBrainz::DiscID.sectors_to_seconds(
|
137
|
+
@fiction_offsets[number]+ @fiction_lengths[number]),
|
138
|
+
track.end_time
|
139
|
+
|
140
|
+
assert_equal track.number, track[:number]
|
141
|
+
assert_equal track.sectors, track[:sectors]
|
142
|
+
assert_equal track.start_sector, track[:start_sector]
|
143
|
+
assert_equal track.end_sector, track[:end_sector]
|
144
|
+
assert_equal track.seconds, track[:seconds]
|
145
|
+
assert_equal track.start_time, track[:start_time]
|
146
|
+
assert_equal track.end_time, track[:end_time]
|
147
|
+
|
148
|
+
assert_equal nil, track[:invalid_value]
|
149
|
+
|
150
|
+
number += 1
|
151
|
+
end
|
152
|
+
|
153
|
+
# Call track_info and retrieve an Array
|
154
|
+
track_info = []
|
155
|
+
assert_nothing_raised {track_info = disc.track_details}
|
156
|
+
assert track_info.is_a?(Array)
|
157
|
+
track_info.each(&proc_test_track)
|
158
|
+
assert_equal disc.last_track_num, number
|
159
|
+
|
160
|
+
# Calling track_info directly with a given block
|
161
|
+
number = 0 # Reset the number of tracks (the above block is a closure, so this works)
|
162
|
+
assert_equal nil, disc.track_details(&proc_test_track)
|
163
|
+
assert_equal disc.last_track_num, number
|
164
|
+
end
|
165
|
+
|
166
|
+
# Test the conversion from sectors to seconds
|
167
|
+
def test_sectors_to_seconds
|
168
|
+
assert_equal 0, MusicBrainz::DiscID.sectors_to_seconds(0)
|
169
|
+
assert_equal @fiction_seconds,
|
170
|
+
MusicBrainz::DiscID.sectors_to_seconds(@fiction_sectors)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mb-discid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: x86-mswin32-60
|
6
|
+
authors:
|
7
|
+
- Philipp Wolfer
|
8
|
+
autorequire: mb-discid
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-19 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: " Ruby bindings for libdiscid. See http://musicbrainz.org/doc/libdiscid\n for more information on libdiscid and MusicBrainz.\n"
|
17
|
+
email: phw@rubyforge.org
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENSE
|
25
|
+
- CHANGES
|
26
|
+
files:
|
27
|
+
- Rakefile
|
28
|
+
- LICENSE
|
29
|
+
- README
|
30
|
+
- CHANGES
|
31
|
+
- examples/discid.rb
|
32
|
+
- ext/mb_discid.c
|
33
|
+
- ext/extconf.rb
|
34
|
+
- lib/mb-discid.rb
|
35
|
+
- test/test_discid.rb
|
36
|
+
- ext/MB_DiscID.so
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://rbrainz.rubyforge.org
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
- ext
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 1.8.7
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements:
|
60
|
+
- libdiscid (http://musicbrainz.org/doc/libdiscid)
|
61
|
+
rubyforge_project: rbrainz
|
62
|
+
rubygems_version: 1.3.5
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Ruby bindings for libdiscid.
|
66
|
+
test_files: []
|
67
|
+
|