VB code to Change MP3 Title updates but does not update

x38class-9313 141 Reputation points
2021-11-27T02:50:19.18+00:00

I have ripped a cd and just for test purposes have put one mp3 in an empty folder (ie it is the only one there).

Explorer shows file name as "Track01.mp3" also Title as "Track01"
Also VLC media player & Windows mediaplayer show Tile as "Track01"

I want to change the Title so I have used CodeProject exmaple:
https://www.codeproject.com/articles/5590/reading-and-writing-mp3-id3v1-tags

attached is moduke from this site MP3ID3v1

This is my code:
Dim objmp3v1 As New MP3ID3v1("C:\Abc\Track01.mp3")

        If objmp3v1.TagExists Then  
            MessageBox.Show(objmp3v1.Frame(MP3ID3v1.FrameTypes.Title))  
        End If  

        objmp3v1.Frame(MP3ID3v1.FrameTypes.Title) = "Summer Time Blues"  
        objmp3v1.Update()  

        If objmp3v1.TagExists Then  
            MessageBox.Show(objmp3v1.Frame(MP3ID3v1.FrameTypes.Title))  
        End If  

When I run my app, the first message box shows "Track01"
so, my app is reading the same as Explorer & VLC Media Player
The second message box shows "Summer Time Blues"

Checking back in Explorer Title shows "Track01", also VLC Media Player

Running my app a second time, the first message box shows "Summer Time Blues"
so, my app is NOT reading the same as Explorer & VLC Media Player (it did the first time)
The second message box shows "Summer Time Blues"

Again, Checking back in Explorer Title shows "Track01", also VLC Media Player
NB: the file Date Time is updated after running my app.

So, What do I need to alter so Explorer & VLC Media Player & Windows Media Player show: "Summer Time Blues"[enter code here][1]

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,668 questions
{count} votes

Accepted answer
  1. Castorix31 83,206 Reputation points
    2021-11-28T07:41:19.803+00:00

    A test by changing the title of a MP3 with IPropertyStore :

    Add at beginning :

    Imports System.Runtime.InteropServices
    

    Main code :

    Dim sFileName As String = "E:\01. IMANY - Don't Be so Shy (Filatov & Karas Remix).mp3"
    Dim sNewTitle As String = "New Title"
    Dim pPropertyStore As IPropertyStore = Nothing
    Dim hr As HRESULT = SHGetPropertyStoreFromParsingName(sFileName, IntPtr.Zero, GETPROPERTYSTOREFLAGS.GPS_READWRITE, GetType(IPropertyStore).GUID, pPropertyStore)
    If hr = HRESULT.S_OK Then
        Dim pv As PROPVARIANT = New PROPVARIANT()
        hr = pPropertyStore.GetValue(PKEY_Title, pv)
        Dim sTitle As String = Marshal.PtrToStringUni(pv.pwszVal)
        Console.WriteLine("Original Title : {0}", sTitle)
    
        Dim pvNew As PROPVARIANT = New PROPVARIANT()
        pvNew.varType = CUShort(VT.VT_LPWSTR)
        pvNew.pwszVal = Marshal.StringToHGlobalUni(sNewTitle)
        hr = pPropertyStore.SetValue(PKEY_Title, pvNew)
        hr = pPropertyStore.Commit()
        Marshal.ReleaseComObject(pPropertyStore)
    End If
    

    with declarations :

    Public Enum HRESULT As Integer
        S_OK = 0
        S_FALSE = 1
        E_NOINTERFACE = &H80004002
        E_NOTIMPL = &H80004001
        E_FAIL = &H80004005
        E_UNEXPECTED = &H8000FFFF
        E_OUTOFMEMORY = &H8007000E
    End Enum
    
    <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Public Shared Function SHGetPropertyStoreFromParsingName(pszPath As String, pbc As IntPtr, flags As GETPROPERTYSTOREFLAGS,
                           ByRef iid As Guid, <[Out](), MarshalAs(UnmanagedType.Interface)> ByRef propertyStore As IPropertyStore) As HRESULT
    End Function
    
    Public Enum GETPROPERTYSTOREFLAGS
        GPS_DEFAULT = 0
        GPS_HANDLERPROPERTIESONLY = &H1
        GPS_READWRITE = &H2
        GPS_TEMPORARY = &H4
        GPS_FASTPROPERTIESONLY = &H8
        GPS_OPENSLOWITEM = &H10
        GPS_DELAYCREATION = &H20
        GPS_BESTEFFORT = &H40
        GPS_NO_OPLOCK = &H80
        GPS_PREFERQUERYPROPERTIES = &H100
        GPS_EXTRINSICPROPERTIES = &H200
        GPS_EXTRINSICPROPERTIESONLY = &H400
        GPS_VOLATILEPROPERTIES = &H800
        GPS_VOLATILEPROPERTIESONLY = &H1000
        GPS_MASK_VALID = &H1FFF
    End Enum
    
    <ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Interface IPropertyStore
        Function GetCount(<Out> ByRef propertyCount As UInteger) As HRESULT
        Function GetAt(<[In]> propertyIndex As UInteger, <Out, MarshalAs(UnmanagedType.Struct)> ByRef key As PROPERTYKEY) As HRESULT
        Function GetValue(<[In], MarshalAs(UnmanagedType.Struct)> ByRef key As PROPERTYKEY, <Out, MarshalAs(UnmanagedType.Struct)> ByRef pv As PROPVARIANT) As HRESULT
        Function SetValue(<[In], MarshalAs(UnmanagedType.Struct)> ByRef key As PROPERTYKEY, <[In], MarshalAs(UnmanagedType.Struct)> ByRef pv As PROPVARIANT) As HRESULT
        Function Commit() As HRESULT
    End Interface
    
    <StructLayout(LayoutKind.Sequential, Pack:=4)>
    Public Structure PROPERTYKEY
        Private fmtid As Guid
        Private pid As Integer
    
        Public ReadOnly Property FormatId As Guid
            Get
                Return Me.fmtid
            End Get
        End Property
    
        Public ReadOnly Property PropertyId As Integer
            Get
                Return Me.pid
            End Get
        End Property
    
        Public Sub New(formatId As Guid, propertyId As Integer)
            Me.fmtid = formatId
            Me.pid = propertyId
        End Sub
    End Structure
    
    <StructLayout(LayoutKind.Sequential)>
    Public Structure PROPARRAY
        Public cElems As UInteger
        Public pElems As IntPtr
    End Structure
    
    <StructLayout(LayoutKind.Explicit, Pack:=1)>
    Public Structure PROPVARIANT
        <FieldOffset(0)>
        Public varType As UShort
        <FieldOffset(2)>
        Public wReserved1 As UShort
        <FieldOffset(4)>
        Public wReserved2 As UShort
        <FieldOffset(6)>
        Public wReserved3 As UShort
        <FieldOffset(8)>
        Public bVal As Byte
        <FieldOffset(8)>
        Public cVal As SByte
        <FieldOffset(8)>
        Public uiVal As UShort
        <FieldOffset(8)>
        Public iVal As Short
        <FieldOffset(8)>
        Public uintVal As UInt32
        <FieldOffset(8)>
        Public intVal As Int32
        <FieldOffset(8)>
        Public ulVal As UInt64
        <FieldOffset(8)>
        Public lVal As Int64
        <FieldOffset(8)>
        Public fltVal As Single
        <FieldOffset(8)>
        Public dblVal As Double
        <FieldOffset(8)>
        Public boolVal As Short
        <FieldOffset(8)>
        Public pclsidVal As IntPtr
        <FieldOffset(8)>
        Public pszVal As IntPtr
        <FieldOffset(8)>
        Public pwszVal As IntPtr
        <FieldOffset(8)>
        Public punkVal As IntPtr
        <FieldOffset(8)>
        Public ca As PROPARRAY
        <FieldOffset(8)>
        Public filetime As System.Runtime.InteropServices.ComTypes.FILETIME
    End Structure
    
    Public Enum VT As Short
        VT_EMPTY = 0
        VT_NULL = 1
        VT_I2 = 2
        VT_I4 = 3
        VT_R4 = 4
        VT_R8 = 5
        VT_CY = 6
        VT_DATE = 7
        VT_BSTR = 8
        VT_DISPATCH = 9
        VT_ERROR = 10
        VT_BOOL = 11
        VT_VARIANT = 12
        VT_UNKNOWN = 13
        VT_DECIMAL = 14
        VT_I1 = 16
        VT_UI1 = 17
        VT_UI2 = 18
        VT_UI4 = 19
        VT_I8 = 20
        VT_UI8 = 21
        VT_INT = 22
        VT_UINT = 23
        VT_VOID = 24
        VT_HRESULT = 25
        VT_PTR = 26
        VT_SAFEARRAY = 27
        VT_CARRAY = 28
        VT_USERDEFINED = 29
        VT_LPSTR = 30
        VT_LPWSTR = 31
        VT_RECORD = 36
        VT_FILETIME = 64
        VT_BLOB = 65
        VT_STREAM = 66
        VT_STORAGE = 67
        VT_STREAMED_OBJECT = 68
        VT_STORED_OBJECT = 69
        VT_BLOB_OBJECT = 70
        VT_CF = 71
        VT_CLSID = 72
        VT_BSTR_BLOB = 4095
        VT_VECTOR = 4096
        VT_ARRAY = 8192
        VT_BYREF = 16384
        VT_RESERVED = &H8000S
        VT_ILLEGAL = &HFFFFS
        VT_ILLEGALMASKED = 4095
        VT_TYPEMASK = 4095
    End Enum
    
    Public Shared ReadOnly PKEY_Title As PROPERTYKEY = New PROPERTYKEY(New Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 2)
    
    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. x38class-9313 141 Reputation points
    2021-11-28T02:46:18.33+00:00

    Well, Castorix31, again thanks for your help with previous problems.
    You mention "The right method is with "IPropertyStore" I have looked for examples & only found something in C which has "#include <shobjidl.h>" and others which don't seem to translate into vb.

    Do I have to entirely replace my code or does "IPropertyStore" just become another statement in my code.
    An example would be appreciated
    Thanks

    0 comments No comments

  2. x38class-9313 141 Reputation points
    2021-11-29T02:41:03.41+00:00

    Not being proficient in the technical structures of VB, it took me a while to sort out.
    So, your assistance is much appreciated & all I can say is "EXCELLENT"
    Much appreciated

    0 comments No comments

  3. x38class-9313 141 Reputation points
    2022-03-26T03:19:13.5+00:00

    Yes it has been a while & all is well, However:

    Rather than post a new question I wondered if this post was still monitored by Castorix31

    What I would like to do is change:
    album Title
    track number
    year
    genre
    composer

    I have looked at the code but cannot see the relationship with what has been mapped

    Any help much appreciated

    0 comments No comments