B4J Question How to use jaudiotagger external library

GuyBooth

Active Member
Licensed User
Longtime User
I am comfortable with B4X, but struggle with techniques that are off the main paths …
Right now, I want to use a library called jaudiotagger to help me manipulate music IDTags. I can look at the API documentation all I want, but I don't see how to implement any of it!http://www.jthink.net/jaudiotagger/javadoc/index.html

I know that I will be looking at runmethods with java objects, but have so far failed to write a single line of code where the runmethod is recognized. So I have really only got as far as this line at the beginning of Main
B4X:
    #AdditionalJar: jaudiotagger-2.0.2
and setting up an initial Class_Global with.
B4X:
Sub Class_Globals
    Private fx As JFX
    Private joAT As JavaObject
End Sub
I also don't understand how to initialize the javaobject in this context.
Is there anyone on the forum who has implemented jaudiotagger in B4X who is willing to help me get started? Or even point me in the right direction in general with using an external library like this?
Thanks.
 

Daestrum

Expert
Licensed User
Longtime User
Quick example, doesn't do much except read the headers etc. (use a later jar as the early ones don't recognise a lot of tags)

B4X:
#Region Project Attributes 
 #MainFormWidth: 600
 #MainFormHeight: 600 
 #AdditionalJar: c:/temp/jaudiotagger-2.2.6-SNAPSHOT.jar  ' where I put the jar file
#End Region
Sub Process_Globals
 Private fx As JFX
 Private MainForm As Form
 Dim audioFile As JavaObject
 Dim audioHeader As JavaObject
 Dim audioTags As JavaObject
 Dim fi As JavaObject
 Dim audioTaggerFileIO As JavaObject
End Sub
Sub AppStart (Form1 As Form, Args() As String)
 MainForm = Form1
 'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
 MainForm.Show
 ' get instance of AudioFileIO so we can read the file
 audioTaggerFileIO.InitializeNewInstance("org.jaudiotagger.audio.AudioFileIO",Null)
 ' file to read must be a java.io.File just pass full path to it
 fi.InitializeNewInstance("java.io.File",Array("Z:/Plex/Shared Music/4 Non-Blondes - What's Going On.mp3"))
 ' read the file and store reference to it in audioFile 
 ' audioFile will assume the correct class by the read as it's a javaobject 
audioFile = audioTaggerFileIO.RunMethod("read",Array(fi))
 ' read the headers from audioFile and put into audioHeaders
 ' again audioHeaders will assume the correct class as it's a java object
 audioHeader = audioFile.RunMethod("getAudioHeader",Null)
 ' log the headers to see what we have
 Log(audioHeader)
 ' read the tags from the audioFile
 audioTags = audioFile.RunMethod("getTag",Null)
 ' log them to see what we got
 Log(audioTags)
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
 Return True
End Sub
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
Well I thought I was making progress but I quickly hit a wall …
The above code, with the following lines

B4X:
        Dim HasField As Boolean
        HasField =    audioTags.RunMethod("hasField", Array("ALBUM"))
        Log($"HasField = ${HasField}"$)
        
        Log(audioTags.RunMethod("hasField", Array("ARTIST")))
        Log(audioTags.RunMethod("hasField", Array("TITLE")))
        Log(audioTags.RunMethod("hasField", Array("GENRE")))
        Log(audioTags.RunMethod("hasField", Array("COMPOSER")))

yielded some positive results:
B4X:
Jan. 24, 2019 11:24:20 A.M. org.jaudiotagger.audio.flac.FlacInfoReader read
INFO: C:\Buffers\CD-R\Ripped Files\Summer Side Of Life-11.flac BlockType:STREAMINFO DataLength:34 isLastBlock:false
Jan. 24, 2019 11:24:20 A.M. org.jaudiotagger.audio.flac.FlacInfoReader read
INFO: C:\Buffers\CD-R\Ripped Files\Summer Side Of Life-11.flac BlockType:SEEKTABLE DataLength:630 isLastBlock:false
Jan. 24, 2019 11:24:20 A.M. org.jaudiotagger.audio.flac.FlacInfoReader read
INFO: C:\Buffers\CD-R\Ripped Files\Summer Side Of Life-11.flac BlockType:VORBIS_COMMENT DataLength:258 isLastBlock:false
Jan. 24, 2019 11:24:20 A.M. org.jaudiotagger.audio.flac.FlacInfoReader read
INFO: C:\Buffers\CD-R\Ripped Files\Summer Side Of Life-11.flac BlockType:PADDING DataLength:8192 isLastBlock:true
(FlacTag) FLAC OGG Tag content:
    VENDOR:reference libFLAC 1.2.1 20070917
    ARTIST:Gordon Lightfoot
    TITLE:Cabaret
    ALBUM:Summer Side Of Life
    DATE:1971
    TRACKNUMBER:11
    GENRE:Folk
    COMMENT:
    BAND:
    ALBUMARTIST:
    COMPOSER:
    DISCNUMBER:1
    TOTALDISCS:1
    TOTALTRACKS:11
HasField = true
true
true
true
true

But I have yet to find a way to extract a single Tag "value". For instance, I want to pull the specific TITLE (Cabaret in the above example) and possibly change it, then write it back to the file.
The examples show several uses (in native java) of extraction using getTagField and getField methods, none of which have led me to any success - typical results are "Method not found" when I try to translate them into runmethod statements in B4J.
The only statement other than the "HasField" example above that has not produced an error is
B4X:
        Dim joFields As JavaObject
        joFields = audioTags.RunMethodJO("getFields", Null)
        Log(joFields)
which results in a message in the log:
B4X:
() org.jaudiotagger.audio.generic.AbstractTag$1@32f0754
I have yet to extract anything from this. I feel as though I am really close, but skating all around the solution.
The documents and example also have references such as FieldKey.ALBUM whose relevance I don't fully understand. I would welcome any insights on where I go from here.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
B4X:
 Log(audioTags.RunMethod("getFirst",Array("ARTIST")))
 Log(audioTags.RunMethod("getFirst",Array("ALBUM")))
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
B4X:
 Log(audioTags.RunMethod("getFirst",Array("ARTIST")))
 Log(audioTags.RunMethod("getFirst",Array("ALBUM")))
This works. I found that the following code was missing from the examples I had found:
B4X:
 private String getTagField(Tag tag, FieldKey fieldKey) {
        try {
            return StringUtils.trimToNull(tag.getFirst(fieldKey));
        } catch (Exception x) {
            // Ignored.
            return null;
        }
    }
which is why I was not successful in using every variation I could think of for .RunMethod("getTagField", FieldKey) code.
 
Upvote 0
Top