For the sake of completeness I've attached the whole project I am trying to build to extract ID tags from flac and mp3 files. I am using the jaudiotagger external library (too large to upload here), and have run into a problem with inconsistency.
When I run the program (from within B4J), I get a set of results. If I re-run the test, multiple times, without closing the program, I get the same results. But if I close the program and restart it (from within B4J) I get different results. Usually (but not always) I get error messages concerning jaudiotagger.tag.Fieldkeys, eg:
Can I do something wrong in my program to produce this inconsistency? I'm not changing any code, parameters or anything else between tests. Just shutting down B4J, restarting it, rerunning the program.
Extracts from the results that demonstrate the problem (I have included three complete sets of logs in a single text file in the attached zip - each set from a different run with different results):
From result set #1 - I consider this to be a "clean" set, the results I expect to see:
From result set #3 - Date = null, Year = empty
The code that produces these results are a Main module and a Class.
Main:
Class clIDTag:
I would love to see a simple solution to this, even if it's a dumb mistake that I have made!
When I run the program (from within B4J), I get a set of results. If I re-run the test, multiple times, without closing the program, I get the same results. But if I close the program and restart it (from within B4J) I get different results. Usually (but not always) I get error messages concerning jaudiotagger.tag.Fieldkeys, eg:
B4X:
java.lang.IllegalArgumentException: No enum constant org.jaudiotagger.tag.FieldKey.DATE
Extracts from the results that demonstrate the problem (I have included three complete sets of logs in a single text file in the attached zip - each set from a different run with different results):
From result set #1 - I consider this to be a "clean" set, the results I expect to see:
B4X:
(FlacTag) FLAC OGG Tag content:
...
ALBUM:Summer Side Of Life
DATE:1971
TRACKNUMBER:05
…
HasField DATE is true
HasField YEAR is false
…
Map Values:
...
DATE, 1971
...
YEAR, Empty
...
From result set #2 - Date = null, Year = 1971
B4X:
(FlacTag) FLAC OGG Tag content:
...
ALBUM:Summer Side Of Life
DATE:1971
TRACKNUMBER:05
...
java.lang.IllegalArgumentException: No enum constant org.jaudiotagger.tag.FieldKey.DATE
HasField YEAR is true
...
Map Values:
...
YEAR, 1971
...
DATE, null
...
From result set #3 - Date = null, Year = empty
B4X:
(FlacTag) FLAC OGG Tag content:
...
ALBUM:Summer Side Of Life
DATE:1971
...
java.lang.IllegalArgumentException: No enum constant org.jaudiotagger.tag.FieldKey.DATE
HasField YEAR is true
...
Map Values:
...
YEAR, Empty
...
DATE, null
The code that produces these results are a Main module and a Class.
Main:
B4X:
#Region Project Attributes
#MainFormWidth: 600
#MainFormHeight: 600
#AdditionalJar: jaudiotagger-2.2.6-SNAPSHOT
#End Region
Sub Process_Globals
Private fx As JFX
Private MainForm As Form
Private btnRunTest As Button
Private SourceFolder As String
Private MusicFile As String
Private IDTagger As clIDTag
End Sub
Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.RootPane.LoadLayout("TestButtonPanel") 'Load the layout file.
MainForm.Show
'' You must set these to a valid folder and music file,
'' For example:
'' SourceFolder = "C:\Buffers\CD-R\RippedFiles"
'' MusicFile = "Summer Side Of Life-05.flac"
'' Flac files seem to be especially troublesome
SourceFolder = "C:/Buffers/CD-R/Ripped Files"
MusicFile = "Summer Side Of Life-05.flac"
IDTagger.Initialize (SourceFolder)
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
Sub btnRunTest_Click
If SourceFolder = "" Or MusicFile = "" Then
fx.Msgbox2(MainForm, "You must enter a valid SourceFolder and MusicFile name in the code in AppStart", _
"Test ID Tags", "", "OK", "", fx.MSGBOX_INFORMATION)
Else
Dim mapTags As Map
mapTags.Initialize
mapTags.Clear
Wait For (IDTagger.Set_TagSet(MusicFile)) Complete (TagIsSet As Boolean)
If TagIsSet Then
wait for (IDTagger.Map_AllTags) Complete (mapTags As Map)
Log($"Map Values:"$)
For Each k As String In mapTags.Keys
If mapTags.Get(k) <> "null" Then
If mapTags.Get(k) <> "" Then
Log($"${k}, ${mapTags.Get(k)}"$)
End If
End If
Next
Log($"Map Values (Empty):"$)
For Each k As String In mapTags.Keys
If mapTags.Get(k) <> "null" Then
If mapTags.Get(k) = "" Then
Log($"${k}, Empty"$)
End If
End If
Next
Log($"Map Values (Null):"$)
For Each k As String In mapTags.Keys
If mapTags.Get(k) = "null" Then
Log($"${k}, null"$)
End If
Next
End If
End If
End Sub
B4X:
Sub Class_Globals
Private fx As JFX
Dim Fi As JavaObject
Dim audioFile As JavaObject
' Dim audioHeader As JavaObject
Dim TagSet As JavaObject
Dim Fi As JavaObject
Dim audioTaggerFileIO As JavaObject
Dim mSourceFolder As String
Dim mapTags As Map
End Sub
'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(Folder As String)
setSourceFolder(Folder)
Fill_TagMap
End Sub
' Change this property if the SourceFolder changes
Public Sub setSourceFolder (sVar As String)
mSourceFolder = sVar
End Sub
Sub Fill_TagMap
' Initialize the Tags map and enter known tags with empty values
mapTags.Initialize
mapTags.Put("ALBUM", "")
mapTags.Put("ARTIST", "")
mapTags.Put("GENRE", "")
mapTags.Put("DATE", "")
mapTags.Put("YEAR", "")
mapTags.Put("DISCNUMBER", "")
mapTags.Put("TOTALDISCS", "")
mapTags.Put("TOTALTRACKS", "")
mapTags.Put("ALBUM", "")
mapTags.Put("TRACKNUMBER", "")
mapTags.Put("TITLE", "")
' May not exist
mapTags.Put("ALBUM_ARTIST", "")
mapTags.Put("COMPOSER", "")
mapTags.Put("CONDUCTOR", "")
mapTags.Put("ORCHESTRA", "")
mapTags.Put("SOLOISTS", "")
mapTags.Put("COMMENT", "")
End Sub
' Run this to set up each new track file
Public Sub Set_TagSet (FileName As String) As ResumableSub
Dim TagIsSet As Boolean
Try
' get an instance of AudioFileIO so we can read the file
audioTaggerFileIO.InitializeNewInstance("org.jaudiotagger.audio.AudioFileIO",Null)
' Check that the file (Folder, Name) exists:
If File.Exists(mSourceFolder, FileName) Then
' file to read must be a java.io.File just pass full path to it
Fi.InitializeNewInstance("java.io.File",Array(File.Combine(mSourceFolder, FileName)))
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)
' read the tags from the audioFile
TagSet = audioFile.RunMethod("getTag",Null)
TagIsSet = True
Else
fx.Msgbox2(Null, $"File ${FileName} not found."$, "TagSet Error", _
"", "OK", "", fx.MSGBOX_ERROR)
End If
Catch
Log($"Exception Message: ${LastException.Message}"$)
End Try
Log(TagSet)
Return TagIsSet
End Sub
Public Sub Map_Tag (Key As String) As ResumableSub
Try
Dim HasField As Boolean
Dim TagValue As String
HasField = TagSet.RunMethod("hasField", Array(Key))
Log($"HasField ${Key} is ${HasField}"$)
If HasField Then
TagValue = TagSet.runmethod("getFirst", Array(Key))
TagValue = TagValue.Trim
Else
TagValue = ""
End If
Catch
Log(LastException.Message)
TagValue = Null
End Try
Return TagValue
End Sub
'
Public Sub Map_AllTags As ResumableSub
For Each s As String In mapTags.Keys
Wait for (Map_Tag (s)) complete (TagValue As String)
mapTags.Put(s, TagValue)
Next
Return mapTags
End Sub