B4J Question MP3 Files

Daestrum

Expert
Licensed User
Longtime User
If you use inline java
B4X:
...
artistName=(String) mp.getMedia().getMetadata().get("artist");
album=(String) mp.getMedia().getMetadata().get("album");
year= (Integer) mp.getMedia().getMetadata().get("year");
title= (String) mp.getMedia().getMetadata().get("title");
if (mp.getMedia().getMetadata().keySet().contains("image")){
image = (Image) mp.getMedia().getMetadata().get("image");
}else{
image = new Image("file:///c:/b4jpics/default.png");// default album art
}
...
Where mp is the MediaPlayer control. (meta data is only available after the mediaplayer is in the 'ready' state)
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I think that it is easier to call such API with JavaObject:
B4X:
Dim jmp As JavaObject = mp 'not sure where it comes from
Dim metadata As JavaObject = jmp.RunMethodJO("getMedia", Null).RunMethod("getMetadata", Null)
Dim Album As String = metadata.RunMethod("get", Array("album"))
Dim Year As Int = metadata.RunMethod("get", Array("year"))
Dim Image As Image = metadata.RunMethod("get", Array("image"))
 
Upvote 0

Robert Valentino

Well-Known Member
Licensed User
Longtime User
This what I came up with.

Needed to make the routine a Resumable Sub because if I do not do the Wait(0), it seems like MeidaPlayer does not load and have the information available


B4X:
  Type   TTrackInfo(   IsValid     As Boolean,   _   ' Is this Data Valid
             FileExists   As Boolean,   _    ' Does this FilePath / FileName Exist
             FilePath   As String,   _   ' File Path
             FileName   As String,   _   ' File Name
             Album     As String,   _   ' Album Name
             Artist     As String,   _   ' Artist Name
             Song     As String,   _   ' Title Name
             Number     As String,   _   ' Track Number
             Year     As String,   _   ' Year of song
             Duration   As Long,   _   ' Duration (who long this track is)                                    
             CoverArt   As Object)


B4X:
Public  Sub ReadMP3File(FilePath As String, FileName As String) As ResumableSub


       Dim MediaPlayer   As MediaPlayer

       Dim TrackInfo  As TTrackInfo

       TrackInfo.Initialize
       TrackInfo.IsValid     = True
    
       If  FilePath.CharAt(FilePath.Length-1) <> "\" Then FilePath = FilePath &"\"
    
       TrackInfo.FilePath     = FilePath
       TrackInfo.FileName     = FileName


       If  File.Exists(FilePath, FileName) = False Then
         TrackInfo.FileExists   = False
         Return TrackInfo
       End If
    
       TrackInfo.FileExists = True
    
       MediaPlayer.Initialize("", File.GetUri(FilePath, FileName))
    
    
       Sleep(0)       '  Need this Sleep so the MediaPlayer will actually load the track and have the info available


       Dim jo_mp      As JavaObject = MediaPlayer 'not sure where it comes from    
    
       Dim metadata    As JavaObject = jo_mp.RunMethodJO("getMedia", Null).RunMethod("getMetadata", Null)


       '--------------------------------------------------------------------------------------------------------------------------
       '  See if we can read the Media info using MetaData - If not try and use what we have in the Database
       '--------------------------------------------------------------------------------------------------------------------------
       TrackInfo.Album         = metadata.RunMethod("get", Array("album"))
       TrackInfo.Album         = TrackInfo.Album.Trim
    
       TrackInfo.Artist       = metadata.RunMethod("get", Array("artist"))
       TrackInfo.Artist       = TrackInfo.Artist.Trim
    
       TrackInfo.Song         = metadata.RunMethod("get", Array("title"))
       TrackInfo.Song         = TrackInfo.Song.Trim
    
       TrackInfo.Number       = metadata.RunMethod("get", Array("track"))          
       TrackInfo.Number       = TrackInfo.Number.Trim
    
       TrackInfo.Year         = metadata.RunMethod("get", Array("year"))
       TrackInfo.Year         = TrackInfo.Year.Trim
    
  
       Dim Duration   As String    = metadata.RunMethod("get", Array("duration"))

       Duration = Duration.Trim
    
       If  Duration.Length > 0 Then
         Dim Space As Int = Duration.LastIndexOf(" ms")

         If  Space <> -1 Then
           Duration = Duration.SubString2(0, Space)
         End If
       End If

       If  IsNumber(Duration) = False Then
         Duration = 0
       Else
         Duration = Duration / 1000
       End If
    
       TrackInfo.Duration     = Duration

       TrackInfo.CoverArt     = metadata.RunMethod("get", Array("image"))              
                              
       If  IsNumber(TrackInfo.Number) = False Or TrackInfo.Number = 0 Then
         Dim TrackOffset As Int = TrackInfo.FileName.IndexOf(" - ")
      
         If  TrackOffset <> -1 Then
           Dim Track As String = TrackInfo.FileName.SubString2(0, TrackOffset)
        
           Track = Track.Trim
        
           If  IsNumber(Track) Then TrackInfo.Number   = Track
         End If
       End If                        

       Return TrackInfo
End Sub



B4X:
Dim TrackInfo As TTrackInfo
  
   Wait For(MusicDB.ReadMP3File("H:\New-Combine\Elvis Presley\The Number One Hits", "04 - Don't Be Cruel.mp3")) Complete(TrackInfo As TTrackInfo)
  
   Log("TrackInfo:" &TrackInfo)


Thanks for the help

BobVal
 
Upvote 0

Robert Valentino

Well-Known Member
Licensed User
Longtime User
a lot of my MP3 files are getting Null when I do the

metadata.RunMethod("get", Array("duration"))

doesn't always return the duration

is there another way of getting the time length of a song?
 
Upvote 0

Robert Valentino

Well-Known Member
Licensed User
Longtime User
Well I changed my code to wait for Status to be Ready and then if Duration is Null get the duration from MediaPlayer

B4X:
Public  Sub ReadMP3File(FilePath As String, FileName As String) As ResumableSub

   
       Dim SomethingNull    As Boolean
       
       Dim MediaPlayer     As MediaPlayer   
   
       Dim TrackInfo     As TTrackInfo

       TrackInfo.Initialize
       TrackInfo.IsValid     = True
       
       If  FilePath.CharAt(FilePath.Length-1) <> "\" Then FilePath = FilePath &"\"
       
       TrackInfo.FilePath     = FilePath
       TrackInfo.FileName     = FileName


       If  File.Exists(FilePath, FileName) = False Then
         TrackInfo.FileExists   = False
         Return TrackInfo
       End If
       
       TrackInfo.FileExists = True
       
       MediaPlayer.Initialize("", File.GetUri(FilePath, FileName))

       Dim jo_mp      As JavaObject = MediaPlayer 'not sure where it comes from       

       Dim Status     As String    = "UNKNOWN"
       
             
       Do  While Status <> "READY"
         Status =  jo_mp.RunMethod("getStatus", Null)         
         Sleep(0)               
       Loop
       

             
       Dim metadata    As JavaObject = jo_mp.RunMethodJO("getMedia", Null).RunMethod("getMetadata", Null)
       
       
       TrackInfo.Number       = 0
       TrackInfo.Duration       = 0
       TrackInfo.Year         = 0
                 
       TrackInfo.Album         = metadata.RunMethod("get", Array("album"))
       TrackInfo.Album         = TrackInfo.Album.Trim
       
       TrackInfo.Artist       = metadata.RunMethod("get", Array("artist"))
       TrackInfo.Artist       = TrackInfo.Artist.Trim
       
       TrackInfo.Song         = metadata.RunMethod("get", Array("title"))
       TrackInfo.Song         = TrackInfo.Song.Trim
       
       TrackInfo.Number       = metadata.RunMethod("get", Array("track"))             
       TrackInfo.Number       = TrackInfo.Number.Trim
       
       TrackInfo.Year         = metadata.RunMethod("get", Array("year"))
       TrackInfo.Year         = TrackInfo.Year.Trim
       
       If  IsNull(TrackInfo.Year) Then
         TrackInfo.Year = 0
       End If
     
       Dim Duration   As String    = metadata.RunMethod("get", Array("duration"))


       Duration = Duration.Trim
         
       If  IsNull(Duration) Then
         Duration = ""
       End If
         
       
       If  Duration.Length > 0 Then
         Dim Space As Int = Duration.LastIndexOf(" ms")
   
         If  Space <> -1 Then
           Duration = Duration.SubString2(0, Space)
         End If
       Else
         Duration = MediaPlayer.Duration           
       End If

       If  IsNumber(Duration) = False Then
         Duration = 0
       Else
         Duration = Duration / 1000
       End If
       
       TrackInfo.Duration     = Duration
         
       If  IsNumber(TrackInfo.Number) = False Or TrackInfo.Number = 0 Then
         Dim TrackOffset As Int = TrackInfo.FileName.IndexOf(" - ")
         
         If  TrackOffset <> -1 Then
           Dim Track As String = TrackInfo.FileName.SubString2(0, TrackOffset)
           
           Track = Track.Trim
           
           If  IsNumber(Track) Then TrackInfo.Number   = Track
         End If
       End If                           
       
       Return TrackInfo

End Sub

Private Sub IsNull(NullCheck As Object) As Boolean
       If  NullCheck = Null Then Return True
       
       If  NullCheck Is String Then
         Dim Test As String = NullCheck
         
         If  Test = "null" Then Return True
       End If
       
       Return False
End Sub
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
If you don't want to use the MediaPlayer control, you can use mp3agic.jar and use JavaObject to access the data that it reads.
eg
just include the jar in #AdditionalJars: ...
B4X:
Dim mp3 As JavaObject
 mp3.InitializeNewInstance("com.mpatric.mp3agic.Mp3File",Array("w:/music/Ace Of Base - All That She Wants.mp3"))
 Log("Length  : "&mp3.RunMethod("getLengthInSeconds",Null)&" seconds")
 Log("BitRate  : "&mp3.RunMethod("getBitrate",Null)&" Kbps")
 Log("Sample Rate : "&mp3.RunMethod("getSampleRate",Null)&" Hz")
 If (mp3.RunMethod("hasId3v1Tag",Null)) Then
 Dim id3v1Tag As JavaObject = mp3.RunMethodJO("getId3v1Tag",Null)
 Log("Track  : "&id3v1Tag.RunMethod("getTrack",Null))
 Log("Artist  : "&id3v1Tag.RunMethod("getArtist",Null))
 Log("Title  : "&id3v1Tag.RunMethod("getTitle",Null))
 Log("Album  : "&id3v1Tag.RunMethod("getAlbum",Null))
 Log("Year  : "&id3v1Tag.RunMethod("getYear",Null))
 Log("Genre  : "&id3v1Tag.RunMethod("getGenre",Null)&" ("&id3v1Tag.RunMethod("getGenreDescription",Null)&")")
 Log("Comment : "&id3v1Tag.RunMethod("getComment",Null))
 End If
It can also read and write the tags and v2 tags for additional information(if the file contains them)
 
Upvote 0

Robert Valentino

Well-Known Member
Licensed User
Longtime User
Fixed Coverart to Preserve Ratio when showing.

Clicking on Image will start / stop playing MP3 File

Including 2nd Zip where I am pretty much doing the same thing but using a TreeTableView
NOTE: Just banged this together - so code is pretty sloppy
 

Attachments

  • MP3Display.zip
    6.6 KB · Views: 346
  • MP3DisplayTTV.zip
    7.7 KB · Views: 327
Last edited:
Upvote 0
Top