robinst / taglib-ruby

Ruby interface for the TagLib C++ library, for reading and writing meta-data (tags) of many audio formats
https://robinst.github.io/taglib-ruby/
MIT License
258 stars 27 forks source link

Taglib 2.0 compatibility? #127

Open q234rty opened 10 months ago

q234rty commented 10 months ago

Taglib has released their 2.0 version removing a few deprecated funtions that taglib-ruby seems to use.

Building taglib-ruby with taglib 2.0 fails with

Build logs

``` current directory: /build/ruby-taglib-ruby/pkg/ruby-taglib-ruby/usr/lib/ruby/gems/3.0.0/gems/taglib-ruby-1.1.3/ext/taglib_base /usr/bin/ruby -I /usr/lib/ruby/3.0.0 extconf.rb checking for -lstdc++... yes checking for -ltag... yes creating Makefile current directory: /build/ruby-taglib-ruby/pkg/ruby-taglib-ruby/usr/lib/ruby/gems/3.0.0/gems/taglib-ruby-1.1.3/ext/taglib_base make DESTDIR\= sitearchdir\=./.gem.20240127-2508-yotc3p sitelibdir\=./.gem.20240127-2508-yotc3p clean current directory: /build/ruby-taglib-ruby/pkg/ruby-taglib-ruby/usr/lib/ruby/gems/3.0.0/gems/taglib-ruby-1.1.3/ext/taglib_base make DESTDIR\= sitearchdir\=./.gem.20240127-2508-yotc3p sitelibdir\=./.gem.20240127-2508-yotc3p compiling taglib_base_wrap.cxx taglib_base_wrap.cxx: In function ‘VALUE taglib_bytevector_to_ruby_string(const TagLib::ByteVector&)’: taglib_base_wrap.cxx:1964:18: error: ‘const class TagLib::ByteVector’ has no member named ‘isNull’ 1964 | if (byteVector.isNull()) { | ^~~~~~ taglib_base_wrap.cxx: In function ‘TagLib::ByteVector ruby_string_to_taglib_bytevector(VALUE)’: taglib_base_wrap.cxx:1973:32: error: ‘null’ is not a member of ‘TagLib::ByteVector’ 1973 | return TagLib::ByteVector::null; | ^~~~ taglib_base_wrap.cxx: In function ‘VALUE taglib_string_to_ruby_string(const TagLib::String&)’: taglib_base_wrap.cxx:1980:14: error: ‘const class TagLib::String’ has no member named ‘isNull’ 1980 | if (string.isNull()) { | ^~~~~~ taglib_base_wrap.cxx: In function ‘TagLib::String ruby_string_to_taglib_string(VALUE)’: taglib_base_wrap.cxx:1991:28: error: ‘null’ is not a member of ‘TagLib::String’ 1991 | return TagLib::String::null; | ^~~~ taglib_base_wrap.cxx: In function ‘VALUE _wrap_File_readableq___(int, VALUE*, VALUE)’: taglib_base_wrap.cxx:4194:32: error: ‘isReadable’ is not a member of ‘TagLib::File’ 4194 | result = (bool)TagLib::File::isReadable((char const *)arg1); | ^~~~~~~~~~ taglib_base_wrap.cxx: In function ‘VALUE _wrap_File_writableq___(int, VALUE*, VALUE)’: taglib_base_wrap.cxx:4221:32: error: ‘isWritable’ is not a member of ‘TagLib::File’ 4221 | result = (bool)TagLib::File::isWritable((char const *)arg1); | ^~~~~~~~~~ taglib_base_wrap.cxx: In function ‘VALUE _wrap_FileRef_create__SWIG_0(int, VALUE*, VALUE)’: taglib_base_wrap.cxx:4738:45: error: ‘create’ is not a member of ‘TagLib::FileRef’ 4738 | result = (TagLib::File *)TagLib::FileRef::create(SWIG_STD_MOVE(arg1),arg2,arg3); | ^~~~~~ taglib_base_wrap.cxx: In function ‘VALUE _wrap_FileRef_create__SWIG_1(int, VALUE*, VALUE)’: taglib_base_wrap.cxx:4769:45: error: ‘create’ is not a member of ‘TagLib::FileRef’ 4769 | result = (TagLib::File *)TagLib::FileRef::create(SWIG_STD_MOVE(arg1),arg2); | ^~~~~~ taglib_base_wrap.cxx: In function ‘VALUE _wrap_FileRef_create__SWIG_2(int, VALUE*, VALUE)’: taglib_base_wrap.cxx:4792:45: error: ‘create’ is not a member of ‘TagLib::FileRef’ 4792 | result = (TagLib::File *)TagLib::FileRef::create(SWIG_STD_MOVE(arg1)); | ^~~~~~ taglib_base_wrap.cxx: In function ‘VALUE taglib_bytevector_to_ruby_string(const TagLib::ByteVector&)’: taglib_base_wrap.cxx:1969:1: warning: control reaches end of non-void function [-Wreturn-type] 1969 | } | ^ taglib_base_wrap.cxx: In function ‘VALUE taglib_string_to_ruby_string(const TagLib::String&)’: taglib_base_wrap.cxx:1987:1: warning: control reaches end of non-void function [-Wreturn-type] 1987 | } | ^ make: *** [Makefile:230: taglib_base_wrap.o] Error 1 make failed, exit code 2 ```

Edit: I didn't regenerate swig headers when building, I guess only the usages of ByteVector::isNull() and ByteVector::null and their String counterparts are real issues :)

q234rty commented 10 months ago

So I attempted to regenerate swig headers with taglib 2.0, and it seems that more workarounds are needed to make swig work with taglib 2.0 as they bumped to C++17.

djvs commented 9 months ago

Archlinux workaround, install taglib1 from AUR and do TAGLIB_DIR=/usr/lib/taglib1 gem install taglib-ruby

q234rty commented 9 months ago

Archlinux workaround, install taglib1 from AUR and do TAGLIB_DIR=/usr/lib/taglib1 gem install taglib-ruby

The taglib1 package has been moved to official repos and it's now installed to a different directory. One can run env CONFIGURE_ARGS="--with-tag-include=/usr/include/taglib1 --with-tag-lib=/usr/lib/taglib1" gem install taglib-ruby instead, or use aur/ruby-taglib-ruby if a AUR package is preferred.

robinst commented 8 months ago

Thanks for raising. I haven't looked at the breaking changes yet.

Maybe we can release a 2.0.0 that requires taglib 2.0, and if necessary release 1.x versions that still work with taglib 1.0.

@jacobvosmaer what do you think?

jacobvosmaer commented 8 months ago

@robinst I was thinking the same thing.

It seems like a lot of work and I wonder how we can break it down into manageable pieces. Perhaps by doing one format at a time?

robinst commented 8 months ago

Yeah. I think the first step is going to be to get the CI build set up to use taglib 2. I've started that here:

Note that it targets a new branch, taglib-2. We can create PRs and target that branch without breaking the main branch. We can go piece by piece; as long as it improves things we can merge it and go ahead, even if the rest is still broken. Then at some point when everything is done, we can merge it to the main branch.

rubyFeedback commented 1 month ago

I can no longer compile the ruby bindings for taglib since a few months; see also other issues created. I am 100% certain that I can use the ruby bindings, because years ago I wrote a GUI in ruby-gtk3, and it worked. (Now I expanded the code base and added querying via ffmpeg.)

The old GUI would then look like this:

https://i.imgur.com/9QIPEOn.png

And the right side, for reading out the tag, I used taglib-ruby.

I think something changed in the API or something.

For instance:

taglib_base_wrap.cxx: In function ‘VALUE _wrap_FileRef_create__SWIG_2(int, VALUE*, VALUE)’:
taglib_base_wrap.cxx:4792:45: error: ‘create’ is not a member of ‘TagLib::FileRef’
 4792 |   result = (TagLib::File *)TagLib::FileRef::create(SWIG_STD_MOVE(arg1));
      |  
 # etc...

I recently transitioned into ffmpeg for reading and writing meta-data of .mp3 files and .mp4 files though. While I think taglib-ruby is cleaner than ffmpeg API-wise (I seem to need to create a local file, in order to then read out the meta-information), ffmpeg is rather reliable. Just notifying you. :)

jacobvosmaer commented 1 month ago

@robinst I think the taglib-2 branch is ready. It passes the tests at least. Shall we merge it into main and then release taglib-ruby 2.0 from main? It would mean main no longer works with taglib 1.x but I think that is OK. People who want to use taglib 1.x can install taglib-ruby 1.x.

robinst commented 1 month ago

@jacobvosmaer Sounds good! Do you want to try doing it? (I don't know if you have all the necessary permissions yet, but happy for you to get them!)

jacobvosmaer commented 4 weeks ago

I have pushed https://github.com/robinst/taglib-ruby/releases/tag/v2.0.0 and https://rubygems.org/gems/taglib-ruby/versions/2.0.0.

robinst commented 3 weeks ago

Awesome, thanks! One more step: Add a release in https://github.com/robinst/taglib-ruby/releases (based on the tag). You can just copy the Markdown from the CHANGELOG.

jacobvosmaer commented 3 weeks ago

OK! https://github.com/robinst/taglib-ruby/releases/tag/v2.0.0