mb-discid 0.1.4-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|