ID3/Metadata/Bitrate/Length

Share your advanced PureBasic knowledge/code with the community.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

ID3/Metadata/Bitrate/Length

Post by Trond »

Windows Media Format 11 SDK is needed. Download it here: http://msdn2.microsoft.com/en-us/window ... 90309.aspx

This code extracts metadata from mp3 and wma files. It must be compiled with unicode enabled.

Code: Select all

Macro GUID(name, l1, w1, w2, b1b2, brest) 
  DataSection
  name:
    Data.l $l1
    Data.w $w1, $w2
    Data.b $b1b2 >> 8, $b1b2 & $FF
    Data.b $brest >> 40 & $FF
    Data.b $brest >> 32 & $FF
    Data.b $brest >> 24 & $FF
    Data.b $brest >> 16 & $FF
    Data.b $brest >> 8 & $FF
    Data.b $brest & $FF
  EndDataSection
EndMacro

GUID(IID_IWMMetadataEditor, 96406bd9, 2b2b, 11d3, b36b, 00c04f6108ff)
GUID(IID_IWMHeaderInfo,     96406bda, 2b2b, 11d3, b36b, 00c04f6108ff)
GUID(IID_IWMHeaderInfo2,    15cf9781, 454e, 482e, b393, 85fae487a810)
GUID(IID_IWMHeaderInfo3,    15CC68E3, 27CC, 4ecd, B222, 3F5D02D80BD5)

#NS_E_SDK_BUFFERTOOSMALL = $C00D0BD4

Enumeration
  #WMT_TYPE_DWORD
  #WMT_TYPE_STRING
  #WMT_TYPE_BINARY
  #WMT_TYPE_BOOL
  #WMT_TYPE_QWORD
  #WMT_TYPE_WORD
  #WMT_TYPE_GUID
EndEnumeration

Interface IWMMetadataEditor Extends IUnknown
  Open(filename.p-unicode)
  Close()
  Flush()
EndInterface

Interface IWMHeaderInfo Extends IUnknown
  GetAttributeCount.l(wStreamNum.W, *pcAttributes.w)
  GetAttributeByIndex.l(wIndex.w, *pwStreamNum.w, pwszName.p-unicode, *pcchNameLen.w, *pType.l, *pValue.b, *pcbLength.w)
  GetAttributeByName(*pwStreamNum.w,  pszName.p-unicode, *pType.l, *pValue.l, *pcbLength.w)
  SetAttribute(wStreamNum.w,  pszName.p-unicode, Type.l,  *pValue.b, cbLength.w)
  GetMarkerCount(*pcMarkers.w)
  GetMarker(wIndex.w, pwszMarkerName.p-unicode, *pcchMarkerNameLen.w, *pcnsMarkerTime.q)
  AddMarker(pwszMarkerName.p-unicode,  cnsMarkerTime.q)
  RemoveMarker(wIndex.w)
  GetScriptCount(*pcScripts.w)
  GetScript(wIndex.w, pwszType.p-unicode, *pcchTypeLen.w, pwszCommand.p-unicode, *pcchCommandLen.w, *pcnsScriptTime.q)
  AddScript(pwszType, pwszCommand.p-unicode, cnsScriptTime.q)
  RemoveScript(wIndex.w)
EndInterface

Interface IWMHeaderInfo2 Extends IWMHeaderInfo
  GetCodecInfoCount(*pcCodecInfos.l)
  GetCodecInfo(wIndex.l, *pcchName.w, pwszName.p-unicode, *pcchDescription.w, pwszDescription.p-unicode, *pCodecType.l, *pcbCodecInfo.w, *pbCodecInfo.b)
EndInterface

Interface IWMHeaderInfo3 Extends IWMHeaderInfo2
  GetAttributeCountEx(wStreamNum.w, *pcAttributes.w)
  GetAttributeIndices(wStreamNum.w, pwszName.p-unicode, *pwLangIndex.w, *pwIndices.w, *pwCount.w)
  GetAttributeByIndexEx(wStreamNum.w, wIndex.w, pwszName.p-unicode, *pwNameLen.w, *pType.l, *pwLangIndex.w, *pValue.b, *pdwDataLength.l)
  ModifyAttribute(wStreamNum.w, wIndex.w, Type.l, wLangIndex.w, *pValue.b, dwLength.l)
  AddAttribute(wStreamNum.w, pszName.p-unicode, *pwIndex.w, Type.l, wLangIndex.w, *pValue.b, dwLength.l)
  DeleteAttribute(wStreamNum, wIndex.w)
  AddCodecInfo(pwszName.p-unicode, pwszDescription.p-unicode, codecType.l, cbCodecInfo.w, *pbCodecInfo.b)
EndInterface

Import "C:\WMSDK\WMFSDK11\lib\wmvcore.lib"
  WMCreateEditor.l(*pIWMMetadataEditor.l)
EndImport

Global medit.IWMMetadataEditor
Global hinfo3.IWMHeaderInfo3

WMCreateEditor(@medit)

medit\Open("C:\Documents and Settings\Trond\Mine dokumenter\Min musikk\yoshida_brothers_-_modan.mp3")
medit\Open("C:\Documents and Settings\Trond\Mine dokumenter\Min musikk\Sufjan Stevens\Illinoise\05 Jacksonville.wma")
medit\QueryInterface(?IID_IWMHeaderInfo3, @hinfo3)

hinfo3\GetAttributeCountEx($FFFF, @c.w)
Debug c

Procedure GetAttribute(Index)
  Define Key.s
  Define Value.l
  Define DataLen.w
  Define Null.s
  
  hinfo3\GetAttributeByIndexEx(0, Index, Null, @KeyLen, @t.b, @l.w, 0, @DataLen)
  Key.s = Space(NameLen)
  If DataLen = 0
    Debug "Invalid data length"
    ProcedureReturn 0
  EndIf
  Value = AllocateMemory(DataLen)
  hinfo3\GetAttributeByIndexEx(0, Index, Key, @KeyLen, @t.b, @l.w, Value, @DataLen)
  Select t
    Case #WMT_TYPE_STRING
      Debug Key + ": " + PeekS(Value)
    Case #WMT_TYPE_DWORD, #WMT_TYPE_BOOL
      Debug Key + ": " + Str(PeekL(Value))
    Case #WMT_TYPE_QWORD
      Debug Key + ": " + StrQ(PeekQ(Value))
    Default
      Debug Key + " has unknown type: " + Str(t)
  EndSelect
  FreeMemory(Value)
EndProcedure

For I = 0 To c-1
  GetAttribute(I)
Next