diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 006a0dc..f8e82fd 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - ruby: [2.6, 2.7, 3.0, jruby, truffleruby] + ruby: [2.6, 2.7, 3.0, 3.1, jruby, truffleruby] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9220c02..6fc2d41 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -43,27 +43,27 @@ Lint/UselessAssignment: # Offense count: 7 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: - Max: 177 + Max: 190 # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 322 + Max: 324 # Offense count: 4 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: - Max: 29 + Max: 36 # Offense count: 8 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: - Max: 117 + Max: 126 # Offense count: 4 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: - Max: 24 + Max: 31 # Offense count: 6 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. diff --git a/Gemfile.lock b/Gemfile.lock index b01f39e..61bb83e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,7 +21,7 @@ GEM simplecov (>= 0.15, < 0.22) docile (1.4.0) flacinfo-rb (1.0) - minitest (5.14.2) + minitest (5.15.0) minitest-rg (5.2.0) minitest (~> 5.0) moumar-wmainfo-rb (0.8) @@ -59,6 +59,7 @@ GEM wavefile (0.6.0) PLATFORMS + ruby universal-java-1.8 x86_64-darwin-20 x86_64-linux @@ -73,4 +74,4 @@ DEPENDENCIES ruby-audioinfo! BUNDLED WITH - 2.2.32 + 2.2.33 diff --git a/lib/audioinfo.rb b/lib/audioinfo.rb index 0f34cbc..051a6d2 100644 --- a/lib/audioinfo.rb +++ b/lib/audioinfo.rb @@ -77,23 +77,24 @@ def initialize(filename, extension = nil) when 'mp3' @info = Mp3Info.new(filename) default_tag_fill - # "TXXX"=> - # ["MusicBrainz TRM Id\000", - # "MusicBrainz Artist Id\000aba64937-3334-4c65-90a1-4e6b9d4d7ada", - # "MusicBrainz Album Id\000e1a223c1-cbc2-427f-a192-5d22fefd7c4c", - # "MusicBrainz Album Type\000album", - # "MusicBrainz Album Status\000official", - # "MusicBrainz Album Artist Id\000"] + # Mp3Info parses additional tags into TXXX if (arr = @info.tag2['TXXX']).is_a?(Array) fields = MUSICBRAINZ_FIELDS.invert arr.each do |val| - if val =~ /^MusicBrainz (.+)\000(.*)$/ - short_name = fields[Regexp.last_match(1)] - @musicbrainz_infos[short_name] = Regexp.last_match(2).gsub("\xEF\xBB\xBF".force_encoding('UTF-8'), '') - end + next unless val =~ /^MusicBrainz (.+)\000(.*)$/ + + short_name = fields[Regexp.last_match(1)] + next unless short_name + + @musicbrainz_infos[short_name] = + Regexp.last_match(2).gsub(String.new("\xEF\xBB\xBF").force_encoding('UTF-8'), '') end end + + # MusicBrainz Track ID is over here: + @musicbrainz_infos['trackid'] = @info.tag2['UFID']&.split("\x00")&.last + @bitrate = @info.bitrate i = @info.tag.tracknum @tracknum = (i.is_a?(Array) ? i.last : i).to_i @@ -124,17 +125,27 @@ def initialize(filename, extension = nil) when 'wma' @info = WmaInfo.new(filename, encoding: 'utf-8') - @artist = @info.tags['Author'] - @album = @info.tags['AlbumTitle'] - @title = @info.tags['Title'] - @tracknum = @info.tags['TrackNumber'].to_i - @date = @info.tags['Year'] + tags = @info.tags.map { |k, v| [k.strip, v.strip] }.to_h + + @artist = tags['Author'] + @album = tags['AlbumTitle'] + @title = tags['Title'] + @tracknum = tags['TrackNumber'].to_i + @date = tags['Year'] @bitrate = @info.info['bitrate'] @length = @info.info['playtime_seconds'] + + info = @info.info.map do |k, v| + [ + k.respond_to?(:strip) ? k.strip : k, + v.respond_to?(:strip) ? v.strip : v + ] + end.to_h + MUSICBRAINZ_FIELDS.each do |key, original_key| @musicbrainz_infos[key] = - @info.info["MusicBrainz/#{original_key.tr(' ', '')}"] || - @info.info["MusicBrainz/#{original_key}"] + info["MusicBrainz/#{original_key.tr(' ', '')}"] || + info["MusicBrainz/#{original_key}"] end when 'mp4', 'aac', 'm4a' diff --git a/ruby-audioinfo.gemspec b/ruby-audioinfo.gemspec index 7111e44..d5b7b59 100644 --- a/ruby-audioinfo.gemspec +++ b/ruby-audioinfo.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.description = "#{spec.summary} Currently, supported formats are: mp3, ogg, mpc, ape, wma, flac, aac, mp4, m4a." spec.homepage = 'https://github.com/moumar/ruby-audioinfo' spec.license = 'GPL-3.0' - spec.required_ruby_version = Gem::Requirement.new('>= 2.6.9') + spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = spec.homepage spec.metadata['changelog_uri'] = 'https://github.com/moumar/ruby-audioinfo/History.txt' diff --git a/test/flac_test.rb b/test/flac_test.rb index 30429a0..32b242b 100644 --- a/test/flac_test.rb +++ b/test/flac_test.rb @@ -12,16 +12,12 @@ class FlacTest < MiniTest::Test FLAC_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.flac" def setup - FileUtils.cp(File.join(SUPPORT_DIR, '440Hz-5sec.flac'), FLAC_FILE) + FileUtils.cp(File.join(SUPPORT_DIR, 'cantina_band.flac'), FLAC_FILE) @i = AudioInfo.new(FLAC_FILE) end - def test_flac_whitelist - assert_kind_of FlacInfo, @i.info - end - - def test_flac_tags_wrapper - assert_kind_of CaseInsensitiveHash, @i.info.tags + def test_default_fields + assert_equal(DEFAULT_INFO.merge('length' => 3.0, 'bitrate' => 216.0859375), @i.to_h) end def test_flac_writing diff --git a/test/m4a_test.rb b/test/m4a_test.rb index 08a9136..59fbf08 100644 --- a/test/m4a_test.rb +++ b/test/m4a_test.rb @@ -13,15 +13,14 @@ def setup @i = AudioInfo.new(M4A_FILE) end - def test_whitelist - assert_kind_of MP4Info, @i.info - end - - def test_length - assert_in_delta(@i.length, 3) + def test_default_fields + assert_equal( + DEFAULT_INFO.slice('artist', 'length', 'tracknum').merge('bitrate' => 113), + @i.to_h.compact + ) end def test_musicbrainz - assert_equal('57c051a1-41db-4764-bfab-ecac5cb3a144', @i.musicbrainz_infos['artistid']) + assert_equal(MUSICBRAINZ_INFO, @i.musicbrainz_infos) end end diff --git a/test/mp3_test.rb b/test/mp3_test.rb new file mode 100644 index 0000000..e635df5 --- /dev/null +++ b/test/mp3_test.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'fileutils' +require 'tmpdir' + +require_relative 'test_helper' + +class MP3Test < MiniTest::Test + MP3_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.mp3" + + # mp3 loads both artists here while some other formats do not + ARTIST = "#{MUSICBRAINZ_INFO['artistid']}/4ebf48b9-9b17-43e2-b4aa-7f29b7e608d1" + + def setup + FileUtils.cp(File.join(SUPPORT_DIR, 'cantina_band.mp3'), MP3_FILE) + @i = AudioInfo.new(MP3_FILE) + end + + def test_default_fields + assert_equal(DEFAULT_INFO.merge('date' => nil, 'length' => 3.056326530612245), @i.to_h) + end + + def test_musicbrainz + assert_equal( + MUSICBRAINZ_INFO.merge('artistid' => ARTIST, 'albumartistid' => ARTIST), + @i.musicbrainz_infos + ) + end +end diff --git a/test/ogg_test.rb b/test/ogg_test.rb new file mode 100644 index 0000000..5d0b8f5 --- /dev/null +++ b/test/ogg_test.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'fileutils' +require 'tmpdir' + +require_relative 'test_helper' + +class OggTest < MiniTest::Test + OGG_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.ogg" + + def setup + FileUtils.cp(File.join(SUPPORT_DIR, 'cantina_band.ogg'), OGG_FILE) + @i = AudioInfo.new(OGG_FILE) + end + + def test_default_fields + assert_equal DEFAULT_INFO.merge('bitrate' => 31.557333333333332), @i.to_h + end +end diff --git a/test/support/440Hz-5sec.flac b/test/support/440Hz-5sec.flac deleted file mode 100644 index a23bf90..0000000 Binary files a/test/support/440Hz-5sec.flac and /dev/null differ diff --git a/test/support/cantina_band.flac b/test/support/cantina_band.flac new file mode 100644 index 0000000..8c41555 Binary files /dev/null and b/test/support/cantina_band.flac differ diff --git a/test/support/cantina_band.mp3 b/test/support/cantina_band.mp3 new file mode 100644 index 0000000..124c299 Binary files /dev/null and b/test/support/cantina_band.mp3 differ diff --git a/test/support/cantina_band.mpc b/test/support/cantina_band.mpc new file mode 100644 index 0000000..165e383 Binary files /dev/null and b/test/support/cantina_band.mpc differ diff --git a/test/support/cantina_band.ogg b/test/support/cantina_band.ogg new file mode 100644 index 0000000..d1c8d30 Binary files /dev/null and b/test/support/cantina_band.ogg differ diff --git a/test/support/cantina_band.wav b/test/support/cantina_band.wav new file mode 100644 index 0000000..af1d918 Binary files /dev/null and b/test/support/cantina_band.wav differ diff --git a/test/support/cantina_band.wma b/test/support/cantina_band.wma new file mode 100644 index 0000000..7126766 Binary files /dev/null and b/test/support/cantina_band.wma differ diff --git a/test/support/piano2.wav b/test/support/piano2.wav deleted file mode 100644 index 12348ef..0000000 Binary files a/test/support/piano2.wav and /dev/null differ diff --git a/test/test_helper.rb b/test/test_helper.rb index 0f6b9cf..ac60751 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -20,3 +20,21 @@ require 'minitest/rg' SUPPORT_DIR = File.expand_path('support', File.dirname(__FILE__)) + +DEFAULT_INFO = { + 'artist' => 'Martin Spitznagel & Bryan Wright', + 'album' => 'Star Wars: Cantina Band in Ragtime', + 'title' => 'Star Wars: Cantina Band in Ragtime', + 'tracknum' => 1, + 'date' => '2011-03-29', + 'length' => 3, + 'bitrate' => 25 +}.freeze + +MUSICBRAINZ_INFO = { + 'albumtype' => 'single', + 'albumid' => 'c357ac93-8896-4486-9630-05ae04c43345', + 'artistid' => '57c051a1-41db-4764-bfab-ecac5cb3a144', + 'albumartistid' => '57c051a1-41db-4764-bfab-ecac5cb3a144', + 'trackid' => '608be633-8a2b-4b90-b745-e38cae815c20' +}.freeze diff --git a/test/wav_test.rb b/test/wav_test.rb index a566889..56421fb 100644 --- a/test/wav_test.rb +++ b/test/wav_test.rb @@ -9,15 +9,15 @@ class TestWav < MiniTest::Test WAV_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.wav" def setup - FileUtils.cp(File.join(SUPPORT_DIR, 'piano2.wav'), WAV_FILE) + FileUtils.cp(File.join(SUPPORT_DIR, 'cantina_band.wav'), WAV_FILE) @i = AudioInfo.new(WAV_FILE) end - def test_wav_whitelist - assert_kind_of WaveFile::Info, @i.info + def test_default_fields + assert_equal({ 'length' => 3.0, 'bitrate' => 352.8645833333333 }, @i.to_h.compact) end - def test_wav_length - assert_in_delta(@i.length, 6.306) + def test_musicbrainz + assert_equal({}, @i.musicbrainz_infos) end end diff --git a/test/wma_test.rb b/test/wma_test.rb new file mode 100644 index 0000000..b9e85d0 --- /dev/null +++ b/test/wma_test.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'fileutils' +require 'tmpdir' + +require_relative 'test_helper' + +class WmaTest < MiniTest::Test + WMA_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.wma" + + def setup + FileUtils.cp(File.join(SUPPORT_DIR, 'cantina_band.wma'), WMA_FILE) + @i = AudioInfo.new(WMA_FILE) + end + + def test_default_fields + assert_equal(DEFAULT_INFO.merge('bitrate' => 24, 'length' => 4), @i.to_h) + end + + def test_musicbrainz + assert_equal MUSICBRAINZ_INFO.sort, @i.musicbrainz_infos.sort + end +end