I searched the internet and found code for getting and setting MP3 tags using PowerShell so I decided to adapt it for QB64 using my pipecom library. It uses a .NET DLL for PowerShell for getting tags and the PowerShell module for setting. You will need to download and install the PowerShell module
here and install it by downloading the zip and extracting it to the modules folder. One could automate an install of this module at runtime if desired. More tags can be set than the ones I have provided but if someone wanted to they could expand this out.
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.AlbumArtists;}" exit_code = pipecom(cmd, stdout, stderr)
GetArtist
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.Album;}" exit_code = pipecom(cmd, stdout, stderr)
GetAlbum
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.Track;}" exit_code = pipecom(cmd, stdout, stderr)
GetTrack
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.Disc;}" exit_code = pipecom(cmd, stdout, stderr)
GetDisc
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.Year;}" exit_code = pipecom(cmd, stdout, stderr)
GetYear
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.FirstGenre;}" exit_code = pipecom(cmd, stdout, stderr)
GetGenre
= Mid$(stdout
, 1, Len(stdout
) - 1)
cmd
= "PowerShell $files = Get-Item '" + Chr$(34) + file
+ Chr$(34) + "'; $null = [System.Reflection.Assembly]::LoadFile('" + Chr$(34) + _CWD$ + "\taglib-sharp.dll" + Chr$(34) + "');foreach($iFile in $files){$mediaFile=[TagLib.File]::Create($iFile.fullname);$mediaFile.Tag.FirstComposer;}" exit_code = pipecom(cmd, stdout, stderr)
GetComposer
= Mid$(stdout
, 1, Len(stdout
) - 1)
exit_code
= _ShellHide("PowerShell Import-Module taglib; Get-ChildItem '" + Chr$(34) + file
+ Chr$(34) + "' ^| set-artist '" + Chr$(34) + Artist
+ Chr$(34) + "'") SetArtist = exit_code
exit_code
= _ShellHide("PowerShell Import-Module taglib; Get-ChildItem '" + Chr$(34) + file
+ Chr$(34) + "' ^| set-title '" + Chr$(34) + Title
+ Chr$(34) + "'") SetTitle = exit_code
exit_code
= _ShellHide("PowerShell Import-Module taglib; Get-ChildItem '" + Chr$(34) + file
+ Chr$(34) + "' ^| set-track " + LTrim$(Str$(Track
))) SetTrack = exit_code
exit_code
= _ShellHide("PowerShell Import-Module taglib; Get-ChildItem '" + Chr$(34) + file
+ Chr$(34) + "' ^| set-disc " + LTrim$(Str$(Disc
))) SetDisc = exit_code
'$INCLUDE:'pipecomqb64.bas'
pipecomqb64.bas:
As Long dwX
, dwY
, dwXSize
, dwYSize
, dwXCountChars
, dwYCountChars
, dwFillAttribute
, dwFlags
As _Offset lpReserved2
, hStdInput
, hStdOutput
, hStdError
Const STARTF_USESTDHANDLES
= &H00000100 Const CREATE_NO_WINDOW
= &H8000000
Const INFINITE
= 4294967295 Const WAIT_FAILED
= &HFFFFFFFF
Dim As _Offset hStdOutPipeRead
, hStdOutPipeWrite
, hStdReadPipeError
, hStdOutPipeError
Dim As SECURITY_ATTRIBUTES sa: sa.nLength
= Len(sa
): sa.lpSecurityDescriptor
= 0: sa.bInheritHandle
= 1
pipecom = -1
pipecom = -1
si.dwFlags = STARTF_USESTDHANDLES
si.hStdError = hStdOutPipeError
si.hStdOutput = hStdOutPipeWrite
si.hStdInput = 0
Dim As PROCESS_INFORMATION pi
Dim As Long dwCreationFlags: dwCreationFlags
= CREATE_NO_WINDOW
ok = CreateProcess(lpApplicationName,_
lpProcessAttributes,_
lpThreadAttributes,_
bInheritHandles,_
dwCreationFlags,_
lpEnvironment,_
lpCurrentDirectory,_
pipecom = -1
ok = HandleClose(hStdOutPipeWrite)
ok = HandleClose(hStdOutPipeError)
buf
= Mid$(buf
, 1, dwRead
) stdout = stdout + buf
buf
= Mid$(buf
, 1, dwRead
) stderr = stderr + buf
If WaitForSingleObject
(pi.hProcess
, INFINITE
) <> WAIT_FAILED
Then ex_stat = 1
ok = HandleClose(hStdOutPipeRead)
ok = HandleClose(hStdReadPipeError)
pipecom = exit_code
pipecom = -1
RemoveChr13:
stream = popen(cmd + " 2>pipestderr", "r")
If fgets
(buffer
, 4096, stream
) <> "" And feof
(stream
) = 0 Then status = pclose(stream)
exit_code = WEXITSTATUS(status)
pipecom = exit_code
pipecom = -1
a = pipecom(cmd, stdout, stderr)
pipecom_lite = stderr
pipecom_lite = stdout
If you choose to only GET tags, rather than SET them, you will only need this DLL: