View Full Version : ID3 Tag reading
father of monstermagnet
April 4th, 2005, 08:31 AM
I was searching for a com object that can write/read id3 tags.
I found cddbcontrol.dll and thought that it is a dll made by creative.
But after searching with a com explorer i saw it's name is CDDBControlAOL.CddbID3Tag.
AOL ?
But it's working...
http://www.dlldump.com/download-dll-files.php/dllfiles/C/cddbcontrol.dll/download.html
Don't forget to register :-)
Write:
if not luacom then
UnloadLuaCom ()
end
LoadLuaCom ()
id3 = luacom.CreateObject ("CDDBControlAOL.CddbID3Tag")
id3:LoadFromFile ("D:\\MP 3\\3-Doors-Down-The-better-life\\3 Doors Down - [05] Be like that.mp3",0)
id3.LeadArtist = "3 Doors Down"
id3.Album = "The better life"
id3.Title = "Be like that"
id3.Genre = "Rock"
id3.Year = "2000"
id3.Comments = "Cool"
id3:SaveToFile ("D:\\MP 3\\3-Doors-Down-The-better-life\\3 Doors Down - [05] Be like that.mp3")
Read:
id3:LoadFromFile ("D:\\MP 3\\3-Doors-Down-The-better-life\\3 Doors Down - [05] Be like that.mp3",0)
print (id3.LeadArtist.."\n",id3.Album.."\n",id3.Title.."\n",id3.Genre.."\n",id3.Year.."\n",id3.Comments)
Promixis
April 4th, 2005, 08:57 AM
does it do id3 v2 tags as well?
father of monstermagnet
April 4th, 2005, 09:05 AM
Yes.
But why AOL ?
Here's a list:
Interfaces:
Interface ICddbID3Tag
GUID: {0306D2A8-B7E2-4EA2-ADC6-78F80D65B1E2}
HelpString: ICddbID3Tag Interface
# Members: Sub QueryInterface(riid as GUID, ppvObj as Void)
# Function AddRef as VT_UI4
# Function Release as VT_UI4
# Sub GetTypeInfoCount(pctinfo as VT_UINT)
# Sub GetTypeInfo(itinfo as VT_UINT, lcid as VT_UI4, pptinfo as Void)
# Sub GetIDsOfNames(riid as GUID, rgszNames as VT_I1, cNames as VT_UINT, lcid as VT_UI4, rgdispid as Long)
# Sub Invoke(dispidMember as Long, riid as GUID, lcid as VT_UI4, wFlags as VT_UI2, pdispparams as DISPPARAMS, pvarResult as Variant, pexcepinfo as EXCEPINFO, puArgErr as VT_UINT)
# Property Get Album as String [property Album]
# Property Put Album as String [property Album]
# Property Get Movie as String [property Movie]
# Property Put Movie as String [property Movie]
# Property Get Title as String [property Title]
# Property Put Title as String [property Title]
# Property Get CopyrightYear as String [property CopyrightYear]
# Property Put CopyrightYear as String [property CopyrightYear]
# Property Get CopyrightHolder as String [property CopyrightHolder]
# Property Put CopyrightHolder as String [property CopyrightHolder]
# Property Get Comments as String [property Comments]
# Property Put Comments as String [property Comments]
# Property Get Label as String [property Label]
# Property Put Label as String [property Label]
# Property Get BeatsPerMinute as String [property BeatsPerMinute]
# Property Put BeatsPerMinute as String [property BeatsPerMinute]
# Property Get LeadArtist as String [property LeadArtist]
# Property Put LeadArtist as String [property LeadArtist]
# Property Get PartOfSet as String [property PartOfSet]
# Property Put PartOfSet as String [property PartOfSet]
# Property Get TrackPosition as String [property TrackPosition]
# Property Put TrackPosition as String [property TrackPosition]
# Property Get Year as String [property Year]
# Property Put Year as String [property Year]
# Property Get Genre as String [property Genre]
# Property Put Genre as String [property Genre]
# Property Get FileId as String [property FileId]
# Property Put FileId as String [property FileId]
# Property Get ISRC as String [property ISRC]
# Property Put ISRC as String [property ISRC]
# Sub LoadFromFile(Filename as String, Readonly as Long) [method LoadFromFile]
# Sub BindToFile(Filename as String, Readonly as Long) [method BindToFile]
# Sub SaveToFile(Filename as String) [method SaveToFile]
# Sub Commit [method Commit]
# Sub Clear [method Clear]
# Sub LoadFromBuffer(Buffer as Variant, BufferSize as Long) [method LoadFromBuffer]
# Function GetBufferSize as Long [method GetBufferSize]
# Sub SaveToBuffer(Buffer as Variant, BufferSize as Long) [method SaveToBuffer]
# Function GetTextFrame(Frame as String) as String [method GetTextFrame]
# Sub SetTextFrame(Frame as String, Text as String) [method SetTextFrame]
Promixis
April 4th, 2005, 09:14 AM
I don't see AOL here. Does the file come with any license info?
father of monstermagnet
April 4th, 2005, 09:20 AM
http://www.motobit.com/tips/detpg_list-id3-tags-script/
father of monstermagnet
April 4th, 2005, 09:27 AM
http://ask.americas.creative.com/SRVS/CGI-BIN/WEBCGI.EXE?New,Kb=ww_english,Company={CEAE216D-8719-4C00-AC9F-03BC258F7B70},VARSET=ws:http://us.creative.com,case=2495
danward79
April 4th, 2005, 11:05 AM
This looks very interesting...
father of monstermagnet
April 4th, 2005, 11:25 AM
Version 1.2.0.48 == CDDBControl Core Module (AOL), company Gracenote (formerly CDDB, Inc.)
Version 1.1.0.27 == CDDBControl Core Module, company CDDB, Inc.
Are there any other com objects that can write/read ?
father of monstermagnet
April 4th, 2005, 11:50 AM
Before i go to bed:
http://www.gracenote.com/gn_products/cddb.html
Found the id3lib com object.
Someone using it ?
A COM wrapper (id3com) is also supplied allowing VB, VBA, VBScript and other COM-enabled languages to use the library.
http://prdownloads.sourceforge.net/id3lib/id3com.dll?use_mirror=puzzle
Good night...
father of monstermagnet
April 9th, 2005, 04:59 AM
The id3com.dll sucks.
The gracenote dll works fine.
The AOL inside the name was a modified version.
But there's an other way ActiveXObject("Shell.Application") to read :lol:
Javascript:
var mp3_file = "D:\\MP 3\\Soundgarden Superunknown\\Kickstand.mp3";
var DETAILS =
{
"FILENAME" :0x0, //0
"SIZE" :0x1, //1
"TITLE" :0xA, //10
"COMMENT" :0xE, //14
"INTERPRET":0x10, //16
"ALBUM" :0x11, //17
"YEAR" :0x12, //18
"TRACK" :0x13, //19
"GENRE" :0x14, //20
"LENGTH" :0x15, //21
"BITRATE" :0x16 //22
};
var VALUES = new Object();
var sh = new ActiveXObject("Shell.Application");
var p = mp3_file.lastIndexOf('\\');
var parent_dir = mp3_file.substr(0,p);
var mp3_name = mp3_file.substr(p+1);
var dir = sh.NameSpace(parent_dir);
var mp3 = dir.ParseName(mp3_name);
var str = '';
for (detail in DETAILS)
{
VALUES[detail] = dir.GetDetailsOf (mp3, DETAILS [detail]);
}
for (value in VALUES)
{
str += value + " = " + VALUES[value] + "\n";
}
WScript.Echo (str);
father of monstermagnet
April 9th, 2005, 06:42 AM
Maybe someone is interessed in this, it's a modified version of the famous
m3u script.
Requires: CDDBControl.CddbID3Tag ActiveX control
Creates a xml file ...
Scans 15 gig in about 1 min !
VBScript:
'***********************************
'BEGIN
'***********************************
Option Explicit
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso,id3, WshShell, cptTot, objArgs, arrFiles(), sExtToGet
Dim driveLetter, pathToScan, fold, nTime, sAppName
Dim IExec, playlistPath
Set fso = CreateObject("Scripting.FileSystemObject")
Set id3 = CreateObject("CDDBControl.CddbID3Tag")
Set WshShell = WScript.CreateObject("WScript.Shell")
sAppName = "Mp3Playlister - Recursive playlist generator"
'-- lowercase file extension to search for
sExtToGet = "mp3"
'***********************************
'Path to Scan
'***********************************
pathToScan = "D:\MP 3\"
'***********************************
nTime = Timer
'-- start scanning
Call startScanning()
'-- clean
Set fso = nothing
Set WshShell = nothing
Set id3 = nothing
'***********************************
'END
'***********************************
'***********************************
'FUNCTIONS:
'***********************************
Sub startScanning()
Dim i, cpt, playlistPath
cptTot = 0
If fso.FolderExists(pathToScan) Then
ReDim arrFiles(0)
Set fold = fso.Getfolder(pathToScan)
playlistPath = fold.path &"\"& fold.Name & ".xml"
'-- recurse folder
Call DoIt(fold)
Else
WshShell.Popup "Folder """& pathToScan &""" does not exist. ", 5, sAppName, 48
Wscript.quit
End If
'-- save playlist if more than 0 entry in it
If (UBound(arrFiles) > 0) Then
Call createAndSavePlaylist(arrFiles, playlistPath)
End If
End Sub
'***********************************
Sub AddFiles(fold)
'-- process all mp3 files in the fold folder
Dim strExt, mpFiles, strName, foldName, foldPath, f, Artist, Album, Genre, id3Title, File
foldPath = fold.Path
Set mpfiles = fold.Files
For each f in mpfiles
strName = f.Name
strExt = LCase(fso.GetExtensionName(strName))
If strExt = sExtToGet Then
id3.LoadFromFile foldPath &"\"& UCase(Left(strName, 1)) & Mid(strName,2,Len(strName)),False
Artist = Replace (id3.LeadArtist,Chr(38),"&")
If Artist = "" Then
Artist = "unknown"
End If
Album = Replace (id3.Album,Chr(38),"&")
If Album = "" Then
Album = "unknown"
End If
id3Title = Replace (id3.Title,Chr(38),"&")
If id3Title = "" Then
id3Title = "unknown"
End If
Genre = Replace (id3.Genre,Chr(38),"&")
If Genre = "" Then
Genre = "unknown"
End If
File = Replace (foldPath & "\" & UCase(Left(strName, 1)) & Mid(strName,2,Len(strName)),Chr(38),"&")
arrFiles(cptTot) = ("<CD><ID3ARTIST>" & Artist & "</ID3ARTIST><ID3ALBUM>" & Album & "</ID3ALBUM><ID3TITLE>" & Id3title & "</ID3TITLE><ID3GENRE>" & Genre & "</ID3GENRE><FILE>" & File & "</FILE></CD>")
ReDim Preserve arrFiles(UBound(arrFiles)+1)
cptTot = cptTot + 1 '-- global counter for processed files
End If
Next
End Sub
'***********************************
Sub createAndSavePlaylist(arrFiles, playlistPath)
Dim txt, txtFile
If Not fso.FileExists(playlistPath) Then
Set txtFile = fso.CreateTextFile(playlistPath,true,false) 'ASCII !!
End If
Set txtFile = fso.GetFile(playlistPath)
Set txt = txtFile.OpenAsTextStream(ForWriting, 0) 'ForWriting , 0 for ASCII (-1 for Unicode)
txt.write("<?xml version='1.0' encoding='ISO-8859-1'?><CATALOG>")
txt.write Join(arrFiles,vbCrLf)
txt.write("</CATALOG>")
txt.close
Set txtFile = nothing
End Sub
'***********************************
Sub DoIt(fold)
'-- recursive scan
Dim sfold, sfoo
Call AddFiles(fold) 'process files in current folder
Set sfold = fold.subfolders
for each sfoo in sfold 'process files in subfolders
Call DoIt(sfoo)
Next
End Sub
'***********************************
'Show created file in IE
'***********************************
Set IExec = CreateObject("InternetExplorer.Application")
playlistPath = fold.path &"\"& fold.Name & ".xml"
IExec.navigate playlistPath
IExec.Visible = 1
Promixis
April 12th, 2005, 06:06 PM
There is an opensource project called mediainfo which looks great for doing id3 and other formats...
quixote
April 12th, 2005, 06:29 PM
That would be cool if you could enter a search string and have the song or album play automatically. I would like to make it voice activated so that I could just say "play prodigy album fat of the land", for example, or "play prodigy song mindfields".
father of monstermagnet
April 12th, 2005, 11:03 PM
That should be possible, if you wanna give it a try.
Here's what i've done so far.
Requires CDDBControl.CddbID3Tag
and
Microsoft XML Core Services
http://www.microsoft.com/downloads/details.aspx?familyid=3144b72b-b4f2-46da-b4b6-c5d7485f2b42&displaylang=en
The vbscript that scans and read the music directory.
'***********************************
'BEGIN
'***********************************
Option Explicit
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso,id3, WshShell, cptTot, objArgs, arrFiles(), sExtToGet
Dim driveLetter, pathToScan, fold, nTime, sAppName
Dim IExec, playlistPath
Set fso = CreateObject("Scripting.FileSystemObject")
Set id3 = CreateObject("CDDBControl.CddbID3Tag")
Set WshShell = WScript.CreateObject("WScript.Shell")
sAppName = "Mp3Playlister - Recursive playlist generator"
'-- lowercase file extension to search for
sExtToGet = "mp3"
'***********************************
'Path to Scan
'***********************************
pathToScan = "D:\MP 3\"
'***********************************
nTime = Timer
'-- start scanning
Call startScanning()
'-- clean
Set fso = nothing
Set WshShell = nothing
Set id3 = nothing
'***********************************
'END
'***********************************
'***********************************
'FUNCTIONS:
'***********************************
Sub startScanning()
Dim i, cpt, playlistPath
cptTot = 0
If fso.FolderExists(pathToScan) Then
ReDim arrFiles(0)
Set fold = fso.Getfolder(pathToScan)
playlistPath = fold.path &"\"& fold.Name & ".xml"
'-- recurse folder
Call DoIt(fold)
Else
WshShell.Popup "Folder """& pathToScan &""" does not exist. ", 5, sAppName, 48
Wscript.quit
End If
'-- save playlist if more than 0 entry in it
If (UBound(arrFiles) > 0) Then
Call createAndSavePlaylist(arrFiles, playlistPath)
End If
End Sub
'***********************************
Sub AddFiles(fold)
'-- process all mp3 files in the fold folder
Dim strExt, mpFiles, strName, foldName, foldPath, f, Artist, Album, Genre, id3Title, File
foldPath = fold.Path
Set mpfiles = fold.Files
For each f in mpfiles
strName = f.Name
strExt = LCase(fso.GetExtensionName(strName))
If strExt = sExtToGet Then
id3.LoadFromFile foldPath &"\"& UCase(Left(strName, 1)) & Mid(strName,2,Len(strName)),False
Artist = Replace (id3.LeadArtist,Chr(38),"&")
If Artist = "" Then
Artist = "unknown"
End If
Album = Replace (id3.Album,Chr(38),"&")
If Album = "" Then
Album = "unknown"
End If
id3Title = Replace (id3.Title,Chr(38),"&")
If id3Title = "" Then
id3Title = "unknown"
End If
Genre = Replace (id3.Genre,Chr(38),"&")
If Genre = "" Then
Genre = "unknown"
End If
File = Replace (foldPath & "\" & UCase(Left(strName, 1)) & Mid(strName,2,Len(strName)),Chr(38),"&")
arrFiles(cptTot) = ("<cd><artist>" & Artist & "</artist><album>" & Album & "</album><title>" & Id3title & "</title><genre>" & Genre & "</genre><file>" & File & "</file></cd>")
ReDim Preserve arrFiles(UBound(arrFiles)+1)
cptTot = cptTot + 1 '-- global counter for processed files
End If
Next
End Sub
'***********************************
Sub createAndSavePlaylist(arrFiles, playlistPath)
Dim txt, txtFile
If Not fso.FileExists(playlistPath) Then
Set txtFile = fso.CreateTextFile(playlistPath,true,false) 'ASCII !!
End If
Set txtFile = fso.GetFile(playlistPath)
Set txt = txtFile.OpenAsTextStream(ForWriting, 0) 'ForWriting , 0 for ASCII (-1 for Unicode)
txt.write("<?xml version='1.0' encoding='ISO-8859-1'?><catalog>")
txt.write Join(arrFiles,vbCrLf)
txt.write("</catalog>")
txt.close
Set txtFile = nothing
End Sub
'***********************************
Sub DoIt(fold)
'-- recursive scan
Dim sfold, sfoo
Call AddFiles(fold) 'process files in current folder
Set sfold = fold.subfolders
for each sfoo in sfold 'process files in subfolders
Call DoIt(sfoo)
Next
End Sub
'***********************************
'Show created file in IE
'***********************************
Set IExec = CreateObject("InternetExplorer.Application")
playlistPath = fold.path &"\"& fold.Name & ".xml"
IExec.navigate playlistPath
IExec.Visible = 1
That prints a xml file.
Then process the xml file and have a sorted html output.
At the moment i link only to the file source to play the files.
Adding more search options is easy, adding a textinput for a string
search a little bit harder...
Output Htm Page based on the DataIsland.htm sample.
Link to the created xml file.
<HTML>
<HEAD>
<TITLE>Untitled</TITLE>
<STYLE>
.catalog_genre_head {background-color:darkGreen;font-size:24pt;color:white;font-family:Impact;}
.catalog_head {background-color:green;font-size:18pt;color:white;font-family:Impact;}
.catalog_row0 {background-color:lightGreen;}
.catalog_row1 {background-color:white;}
.catalog_row_end {background-color:darkGreen;}
</STYLE>
</HEAD>
<BODY>
<H1>Music Catalog</H1>
Select a genre to see all songs in that genre:</P>
<DIV id="catalog_table"></DIV>
<xml id="music_catalog" src="MP 3.xml">
</xml>
<xml id="catalog_filter">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="selected_genre" select="'all'"/>
<xsl:template match="/">
<div>
<form method="post" action="catalog.asp">
Genre
<select name="genre" value="{$selected_genre}" onchange="showGenre(this.value)">
<option value="all"><xsl:if test="$selected_genre='all'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>All</option>
<option value="Rock"><xsl:if test="$selected_genre='Rock'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>Rock</option>
<option value="Punk Rock"><xsl:if test="$selected_genre='Punk Rock'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>Punk Rock</option>
<option value="Pop"><xsl:if test="$selected_genre='Pop'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>Pop</option>
<option value="Heavy Metal"><xsl:if test="$selected_genre='Heavy Metal'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>Heavy Metal</option>
<option value="Comedy"><xsl:if test="$selected_genre='Comedy'"><xsl:attribute name="selected">Selected</xsl:attribute></xsl:if>Comedy</option>
</select>
</form>
<xsl:apply-templates select="catalog"/>
</div>
</xsl:template>
<xsl:template match="catalog">
<table width="750" class="catalog_table">
<xsl:apply-templates select="cd[($selected_genre='all') or ($selected_genre=./genre)]">
<xsl:sort select="artist"/>
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="cd">
<xsl:if test="position()=1">
<tr class="catalog_genre_head"><td colspan="5">
<xsl:choose>
<xsl:when test="$selected_genre='all'">
All Genres
</xsl:when>
<xsl:otherwise>
Genre: <xsl:value-of select="genre"/>
</xsl:otherwise>
</xsl:choose>
</td></tr>
<tr class="catalog_head">
<td>#</td>
<td>Artist</td>
<td>Album</td>
<td>Title</td>
<xsl:if test="$selected_genre='all'">
<td>Genre</td>
</xsl:if>
</tr>
</xsl:if>
<tr class="catalog_row{position() mod 2}">
<td><xsl:value-of select="position()"/></td>
<td class="catalog_cell"><xsl:value-of select="artist"/></td>
<td class="catalog_cell"><xsl:value-of select="album"/></td>
<td class="catalog_cell"><xsl:value-of select="title"/> ({file})</td>
<xsl:if test="$selected_genre='all'">
<td class="catalog_cell"><xsl:value-of select="genre"/></td>
</xsl:if>
</tr>
<xsl:if test="position()=last()">
<tr class="catalog_row_end"><td colspan="4"> </td></tr>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
</xml>
<SCRIPT language="JavaScript">
function loadSource(sourceObj){
var xmlDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument.4.0");
xmlDoc.async=false;
xmlDoc.load(sourceObj.XMLDocument);
return xmlDoc;
}
var table_proc=null;
function getProcessor(transformObj){
if (table_proc==null){
var xslDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument.4.0");
var xslTemplate=new ActiveXObject("MSXML2.XSLTemplate.4.0");
xslDoc.async=false;
xslDoc.load(transformObj.XMLDocument);
xslTemplate.stylesheet=xslDoc;
xslProcessor=xslTemplate.createProcessor();
table_proc=xslProcessor;
}
else {
xslProcessor=table_proc;
}
return xslProcessor;
}
function transformData(srcDoc,processor){
var resultDoc=new ActiveXObject("MSXML.DOMDocument");
processor.input=srcDoc;
processor.output=resultDoc;
processor.transform();
return resultDoc;
}
function showGenre(genre){
var srcDoc=loadSource(music_catalog);
var processor=getProcessor(catalog_filter);
processor.addParameter("selected_genre",genre);
var rsltDoc=transformData(srcDoc,processor);
catalog_table.innerHTML=rsltDoc.xml
}
showGenre("all");
</SCRIPT>
</BODY>
</HTML>
quixote
April 13th, 2005, 04:42 AM
That's really nice. I'll give it a shot when I get back from work today. Thanks!
Powered by vBulletin® Version 4.1.8 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.