jamescallmebrent-earworm 0.0.3

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.
@@ -0,0 +1,3 @@
1
+ .*.swp
2
+ doc
3
+ pkg
@@ -0,0 +1,13 @@
1
+ === 0.0.2
2
+
3
+ * 1 Bugfix
4
+
5
+ * Oop! Forgot a require. Thanks Mike McKay!
6
+ * Added better error messaging. Thanks again to Mike McKay.
7
+
8
+ === 0.0.1 / 2008-08-01
9
+
10
+ * 1 major enhancement
11
+
12
+ * Birthday!
13
+
@@ -0,0 +1,12 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/earworm
6
+ lib/earworm.rb
7
+ lib/earworm/client.rb
8
+ lib/earworm/fingerprint.rb
9
+ lib/earworm/puid.rb
10
+ lib/earworm/track.rb
11
+ lib/earworm_lib.rb
12
+ test/test_earworm.rb
@@ -0,0 +1,66 @@
1
+ = earworm
2
+
3
+ * http://earworm.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Earworm can identify unknown music using MusicDNS and libofa.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Identifies mp3, ogg, and wav files.
12
+
13
+ == SYNOPSIS:
14
+
15
+ Identify an unknown audio file:
16
+
17
+ ew = Earworm::Client.new('MY Music DNS Key')
18
+ info = ew.identify(:file => '/home/aaron/unknown.wav')
19
+ puts "#{info.artist_name} - #{info.title}"
20
+
21
+ Fetch info for a PUID:
22
+
23
+ ew = Earworm::Client.new('MY Music DNS Key')
24
+ info = ew.identify(:puid => 'f39d4c68-ab2d-5067-9a1a-c6b45a367906')
25
+ puts "#{info.artist_name} - #{info.title}"
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * {MusicDNS key}[https://secure.musicip.com/dns/index.jsp]
30
+ * libofa
31
+ * icanhasaudio
32
+
33
+ == INSTALL:
34
+
35
+ OS X:
36
+ * sudo port install libogg libvorbis lame libofa
37
+ * gem install earworm
38
+
39
+ Linux:
40
+ * sudo yum install libogg-devel libvorbis-devel lame-devel libofa
41
+ * gem install earworm
42
+
43
+ == LICENSE:
44
+
45
+ (The MIT License)
46
+
47
+ Copyright (c) 2008 {Aaron Patterson}[http://tenderlovemaking.com/]
48
+
49
+ Permission is hereby granted, free of charge, to any person obtaining
50
+ a copy of this software and associated documentation files (the
51
+ 'Software'), to deal in the Software without restriction, including
52
+ without limitation the rights to use, copy, modify, merge, publish,
53
+ distribute, sublicense, and/or sell copies of the Software, and to
54
+ permit persons to whom the Software is furnished to do so, subject to
55
+ the following conditions:
56
+
57
+ The above copyright notice and this permission notice shall be
58
+ included in all copies or substantial portions of the Software.
59
+
60
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
61
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
62
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
63
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
64
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
65
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
66
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |s|
6
+ s.name = "earworm"
7
+ s.email = "aaronp@rubyforge.org"
8
+ s.homepage = "http://github.com/tenderlove/earworm"
9
+ s.authors = ["Aaron Patterson"]
10
+ s.summary = 'What is that song? Earworm uses libofa and MusicDNS to tell you.'
11
+ s.description = 'Earworm can identify unknown music using MusicDNS and libofa.'
12
+ s.rubyforge_project = 'earworm'
13
+ s.add_dependency('icanhasaudio','>=0.1.1')
14
+ # Jeweler defaults
15
+ s.has_rdoc = false
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'earworm'
5
+ require 'yaml'
6
+
7
+ CONFIG = File.join(File.expand_path(ENV['HOME']), '.earworm')
8
+ begin
9
+ config = YAML.load_file(CONFIG)
10
+ rescue
11
+ raise "Please create a .earworm file in your home directory"
12
+ end
13
+
14
+ (puts("USAGE: #{$0} unknown_file") || exit) unless ARGV[0]
15
+
16
+ begin
17
+ ew = Earworm::Client.new(config['key'])
18
+ rescue
19
+ raise "\n\nYou need to generate a key here: http://www.musicip.com/dns/license.jsp\n then put the key into your .earworm file like this:
20
+ key: 012321312AA\n"
21
+ end
22
+ track =
23
+ if File.exists?(ARGV[0])
24
+ ew.identify(:file => ARGV[0])
25
+ else
26
+ ew.identify(:puid => ARGV[0])
27
+ end
28
+
29
+ puts "Title: #{track.title}" if track.title
30
+ puts "Artist: #{track.artist}" if track.artist
31
+ track.puid_list.each do |puid|
32
+ puts "PUID: #{puid}"
33
+ end
34
+
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{earworm}
5
+ s.version = "0.0.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aaron Patterson"]
9
+ s.date = %q{2009-07-05}
10
+ s.default_executable = %q{earworm}
11
+ s.description = %q{Earworm can identify unknown music using MusicDNS and libofa.}
12
+ s.email = %q{aaronp@rubyforge.org}
13
+ s.executables = ["earworm"]
14
+ s.extra_rdoc_files = [
15
+ "README.txt"
16
+ ]
17
+ s.files = [
18
+ ".gitignore",
19
+ "History.txt",
20
+ "Manifest.txt",
21
+ "README.txt",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "bin/earworm",
25
+ "earworm.gemspec",
26
+ "lib/earworm.rb",
27
+ "lib/earworm/client.rb",
28
+ "lib/earworm/fingerprint.rb",
29
+ "lib/earworm/puid.rb",
30
+ "lib/earworm/track.rb",
31
+ "lib/earworm_lib.rb",
32
+ "test/test_earworm.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/tenderlove/earworm}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubyforge_project = %q{earworm}
38
+ s.rubygems_version = %q{1.3.4}
39
+ s.summary = %q{What is that song? Earworm uses libofa and MusicDNS to tell you.}
40
+ s.test_files = [
41
+ "test/test_earworm.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<icanhasaudio>, [">= 0.1.1"])
50
+ else
51
+ s.add_dependency(%q<icanhasaudio>, [">= 0.1.1"])
52
+ end
53
+ else
54
+ s.add_dependency(%q<icanhasaudio>, [">= 0.1.1"])
55
+ end
56
+ end
@@ -0,0 +1,28 @@
1
+ require 'icanhasaudio'
2
+ require 'tempfile'
3
+ require 'earworm_lib'
4
+ require 'earworm/track'
5
+ require 'earworm/puid'
6
+ require 'earworm/fingerprint'
7
+ require 'earworm/client'
8
+ require 'rexml/document'
9
+ require 'rexml/parsers/pullparser'
10
+ require 'net/http'
11
+ require 'tempfile'
12
+
13
+ module Earworm
14
+ VERSION = '0.0.2'
15
+ URL = 'http://ofa.musicdns.org/ofa/1/track'
16
+ class << self
17
+ def ofa_version
18
+ major = DL.malloc(DL.sizeof('I'))
19
+ minor = DL.malloc(DL.sizeof('I'))
20
+ rev = DL.malloc(DL.sizeof('I'))
21
+ major.struct!('I', 'val')
22
+ minor.struct!('I', 'val')
23
+ rev.struct!('I', 'val')
24
+ EarwormLib.ofa_get_version(major, minor, rev)
25
+ "#{major['val']}.#{minor['val']}.#{rev['val']}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ module Earworm
2
+ class Client
3
+ attr_accessor :client_id
4
+ def initialize(client_id)
5
+ @client_id = client_id
6
+ end
7
+
8
+ def identify(options = {})
9
+ post_opts = nil
10
+ if options.key?(:file)
11
+ post_opts = {
12
+ 'cid' => @client_id,
13
+ 'cvr' => "Earworm #{VERSION}",
14
+ 'rmd' => 1,
15
+ 'enc' => '',
16
+ }.merge(Fingerprint.new(options[:file]).to_hash)
17
+ end
18
+ if options.key?(:puid)
19
+ post_opts = {
20
+ 'cid' => @client_id,
21
+ 'cvr' => "Earworm #{VERSION}",
22
+ 'rmd' => 1,
23
+ 'enc' => '',
24
+ }.merge(PUID.new(options[:puid]).to_hash)
25
+ end
26
+ xml = Net::HTTP.post_form(URI.parse(URL), post_opts).body
27
+ parser = REXML::Parsers::PullParser.new(xml)
28
+ track = Track.new
29
+ while parser.has_next?
30
+ thing = parser.pull
31
+ if thing.start_element?
32
+ case thing[0]
33
+ when 'title'
34
+ track.title = parser.pull[0]
35
+ when 'name'
36
+ track.artist_name = parser.pull[0]
37
+ when 'puid'
38
+ track.puid_list << thing[1]['id']
39
+ end
40
+ end
41
+ end
42
+ track
43
+ end
44
+
45
+ def fingerprint(filename)
46
+ Fingerprint.new(filename).to_s
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,122 @@
1
+ module Earworm
2
+ class Fingerprint
3
+ def initialize(thing)
4
+ @thing = thing
5
+ @hash = nil
6
+ end
7
+
8
+ def to_hash
9
+ return @hash if @hash
10
+ info = nil
11
+ @hash = {
12
+ 'art' => 'unknown',
13
+ 'ttl' => 'unknown',
14
+ 'alb' => 'unknown',
15
+ 'tnm' => 0,
16
+ 'gnr' => 'unknown',
17
+ 'yrr' => 0,
18
+ 'brt' => 0,
19
+ 'fmt' => 'wav',
20
+ }
21
+
22
+ if @thing.is_a?(IO)
23
+ info = wav_info_for(@thing)
24
+ elsif @thing.is_a?(Tempfile)
25
+ tmpfile = case @thing.content_type
26
+ when /mpeg$/
27
+ @hash['fmt'] = 'mp3'
28
+ begin
29
+ require 'id3lib'
30
+ @hash = @hash.merge(id3_info_for(@thing.path))
31
+ rescue LoadError
32
+ end
33
+ decode_mp3(@thing.path)
34
+ when /ogg$/
35
+ @hash['fmt'] = 'ogg'
36
+ decode_ogg(@thing.path)
37
+ else # Assume its a wav file
38
+ @thing.path
39
+ end
40
+ File.open(tmpfile, 'rb') { |f|
41
+ info = wav_info_for(f)
42
+ }
43
+ else
44
+ tmpfile = case @thing
45
+ when /mp3$/
46
+ @hash['fmt'] = 'mp3'
47
+ begin
48
+ require 'id3lib'
49
+ @hash = @hash.merge(id3_info_for(@thing))
50
+ rescue LoadError
51
+ end
52
+ decode_mp3(@thing)
53
+ when /ogg$/
54
+ @hash['fmt'] = 'ogg'
55
+ decode_ogg(@thing)
56
+ else # Assume its a wav file
57
+ @thing
58
+ end
59
+ File.open(tmpfile, 'rb') { |f|
60
+ info = wav_info_for(f)
61
+ }
62
+ end
63
+ @hash['fpt'] = info[:fpt]
64
+ @hash['dur'] = info[:milliseconds]
65
+ @hash
66
+ end
67
+
68
+ def to_s
69
+ to_hash['fpt']
70
+ end
71
+
72
+ private
73
+ def wav_info_for(io)
74
+ header = io.read(4).unpack('N').first
75
+ raise unless header == Audio::MPEG::Encoder::WAV_ID_RIFF
76
+ info = Audio::MPEG::Encoder.parse_wave_header(io)
77
+ bytes_in_seconds = 135 * info[:in_samplerate] * 2 * info[:num_channels]
78
+ read_bytes =
79
+ if info[:bytes_in_seconds] > bytes_in_seconds
80
+ bytes_in_seconds
81
+ else
82
+ info[:bytes_in_seconds]
83
+ end
84
+
85
+ data = io.read(read_bytes)
86
+ info[:fpt] = EarwormLib.ofa_create_print( data,
87
+ 0,
88
+ read_bytes/2,
89
+ info[:in_samplerate], 1)
90
+ info
91
+ end
92
+
93
+ def id3_info_for(filename)
94
+ tag = ID3Lib::Tag.new(filename)
95
+ {
96
+ 'art' => tag.artist,
97
+ 'ttl' => tag.title,
98
+ 'alb' => tag.album,
99
+ 'tnm' => tag.track[/^(\d+)/],
100
+ 'gnr' => tag.genre,
101
+ 'yrr' => tag.year,
102
+ }
103
+ end
104
+
105
+ {
106
+ 'ogg' => Audio::OGG::Decoder,
107
+ 'mp3' => Audio::MPEG::Decoder,
108
+ }.each do |type,klass|
109
+ define_method(:"decode_#{type}") do |filename|
110
+ reader = klass.new
111
+ name = File.join(Dir::tmpdir,
112
+ "#{File.basename(filename, ".#{type}")}.wav")
113
+ File.open(filename, 'rb') { |input|
114
+ File.open(name, 'wb') { |tmpfile|
115
+ reader.decode(input, tmpfile)
116
+ }
117
+ }
118
+ name
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,21 @@
1
+ module Earworm
2
+ class PUID
3
+ def initialize(puid)
4
+ @puid = puid
5
+ end
6
+
7
+ def to_hash
8
+ {
9
+ 'puid' => @puid,
10
+ 'art' => 'unknown',
11
+ 'ttl' => 'unknown',
12
+ 'alb' => 'unknown',
13
+ 'tnm' => 0,
14
+ 'gnr' => 'unknown',
15
+ 'yrr' => 0,
16
+ }
17
+ end
18
+
19
+ def to_s; @puid; end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Earworm
2
+ class Track
3
+ attr_accessor :title, :artist_name, :puid_list
4
+ alias :artist :artist_name
5
+ def initialize
6
+ @title = nil
7
+ @artist_name = nil
8
+ @puid_list = []
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ require 'dl/import'
2
+ module EarwormLib # :nodoc:
3
+ extend DL::Importable
4
+ loaded = false
5
+ libs = %w{ libofa.dylib libofa.so libofa.so.0 }
6
+ dirs = %w{ /opt/local/lib /usr/local/lib }
7
+ libs += libs.map { |lib| dirs.map { |dir| File.join(dir, lib) } }.flatten
8
+ libs.each do |so|
9
+ begin
10
+ dlload(so)
11
+ loaded = true
12
+ break
13
+ rescue
14
+ next
15
+ end
16
+ end
17
+ raise "Please install libofa" unless loaded
18
+
19
+ extern "void ofa_get_version(int *, int *, int *)"
20
+ extern "const char * ofa_create_print(const char *, int, long, int, int)"
21
+ end
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'earworm'
4
+ require 'yaml'
5
+
6
+ class EarwormTest < Test::Unit::TestCase
7
+ def setup
8
+ settings = YAML.load_file(File.join(ENV['HOME'], '.earworm'))
9
+ assert settings
10
+ assert settings['assets']
11
+ assert settings['key']
12
+ @assets = settings['assets']
13
+ @key = settings['key']
14
+ @mp3 = Dir[@assets + "/*.mp3"].first
15
+ end
16
+
17
+ def test_ofa_version
18
+ assert Earworm.ofa_version
19
+ end
20
+
21
+ def test_fingerprint
22
+ ew = Earworm::Client.new('123')
23
+ key = ew.fingerprint(@mp3)
24
+ assert key
25
+ end
26
+
27
+ def test_identify_file
28
+ ew = Earworm::Client.new(@key)
29
+ info = ew.identify(:file => @mp3)
30
+ assert info
31
+ assert info.artist_name
32
+ assert info.title
33
+ assert info.puid_list.length > 0
34
+ end
35
+
36
+ def test_idenfity_puid
37
+ ew = Earworm::Client.new(@key)
38
+ info = ew.identify(:puid => 'f39d4c68-ab2d-5067-9a1a-c6b45a367906')
39
+ assert info
40
+ assert info.artist_name
41
+ assert info.title
42
+ assert info.puid_list.length > 0
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jamescallmebrent-earworm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Patterson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-05 00:00:00 -07:00
13
+ default_executable: earworm
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: icanhasaudio
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.1
24
+ version:
25
+ description: Earworm can identify unknown music using MusicDNS and libofa.
26
+ email: aaronp@rubyforge.org
27
+ executables:
28
+ - earworm
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.txt
33
+ files:
34
+ - .gitignore
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - VERSION
40
+ - bin/earworm
41
+ - earworm.gemspec
42
+ - lib/earworm.rb
43
+ - lib/earworm/client.rb
44
+ - lib/earworm/fingerprint.rb
45
+ - lib/earworm/puid.rb
46
+ - lib/earworm/track.rb
47
+ - lib/earworm_lib.rb
48
+ - test/test_earworm.rb
49
+ has_rdoc: false
50
+ homepage: http://github.com/tenderlove/earworm
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: earworm
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: What is that song? Earworm uses libofa and MusicDNS to tell you.
75
+ test_files:
76
+ - test/test_earworm.rb