Description:
The ExtractFields script lets you change tags/fields using the contents of the existing tags.
Typically, this script is used to split titles received from FreeDB (when they contain Title - Artist), to copy or swap fields, to remove leading track numbers, ...
![Image](http://home.scarlet.be/ruben.castelein/MM/ScriptsStorage/AutoScripts/ExtractFields.png)
You can use different "entry lines". Each entry line gets/puts it's information from/in the specified information field (chosen from the dropdown list). The mask that you specify will make sure that the chosen information field gets parsed and the other fields are filled with the info, or that the chosen information field will be filled like specified in the mask.
This script is generally applicable and can be used to replace scripts like:
- SwapArtistTitle
- SwitchOrCopyFields
- Split Artist Title
and maybe other.
The script can be accessed through menu Tools > Scripts > "Extract Fields...", or from the button added to the standard toolbar.
The default shortcut key is Ctrl+Alt+X
When the "Extract Fields" button is clicked, the selected songs *at that moment* are used (not the songs that were selected before you opened the form). So you can still change the songs selection while the form is open.
The "USER DEFAULTS" section on top of the script contains default values that are used when the script starts. You can change this yourself.
Make sure that def_TagField contains a value mentioned in SongDataFields (bottom of the script), and that def_TagMask is a mask that can contain variables mentioned in CommonTags (bottom of the script).
The script needs MediaMonkey version 2.5.3 or above.
Installing manually:
The script below is an auto-script. The Faq "How do I install scripts?" http://faq.mediamonkey.com/index.php?ac ... artlang=en explains how to install it.
Quicky: Copy the code below to a plain text file (e.g. using NotePad) and save it as ExtractFields.vbs. Put that file in MediaMonkey's Scripts\Auto folder and (re)start MediaMonkey.
The script consists of 1 standalone script file ("ExtractFields.vbs")
ExtractFields.vbs (for the Scripts\Auto folder)
Code: Select all
'====================================================================================
' MEDIAMONKEY SCRIPT: ExtractFields v0.1.4 (last updated 2007-08-17) by Steegy
'
' Change tags/fields using the contents of the existing tags.
'====================================================================================
Option Explicit
'*****************************************************
'**** USER DEFAULTS ****
'*****************************************************
Const def_EntryLinesCnt = 2
Const def_TagField = "Title"
Const def_TagMask = "%A - %S"
'*****************************************************
'**** SCRIPT PROPERTIES ****
'*****************************************************
Const RequiredMMVersion = 253
Const ScriptName = "ExtractFields"
Const ScriptCaption = "Extract Fields..."
Const ScriptHint = "Change tags based on existing tags"
Const ScriptShortCut = "Ctrl+Alt+X"
'*****************************************************
'**** GLOBAL DECLARATIONS ****
'*****************************************************
Dim Form, lblMasks, edtMasks, SpinEdit, lblPemTag, btnPem, lblPemValue, lblSpin, btnSpin, btnClose, btnExtractFields
Dim NumberOfEntryLines
Dim DataFieldsArray()
Dim MaskTextArray()
Dim EnableStateArray()
Dim DirectionArray()
Dim ParseEntryMethod
Const pemSerial = 1
Const pemParallel = 2
Dim FSO : Set FSO = CreateObject("Scripting.Filesystemobject")
'*****************************************************
'**** ENTRY POINT ****
'*****************************************************
Sub OnStartup
Dim CurrentVersion : CurrentVersion = SDB.VersionHi & SDB.VersionLo & SDB.VersionRelease
If CurrentVersion < RequiredMMVersion Then
Dim RequiredMMVersionString : RequiredMMVersionString = Mid(RequiredMMVersion, 1, 1) & "." & Mid(RequiredMMVersion, 2, 1) & "." & Mid(RequiredMMVersion, 3, 1)
Dim Text
Text = "'" & ScriptName & "' needs MediaMonkey " & RequiredMMVersionString & " or above." + vbNewLine
Text = Text & "Please Download the latest Version on http://www.MediaMonkey.com" & vbNewLine & vbNewLine
SDB.MessageBox Text, mtError, Array(mbOK)
Else
Dim MenuItem : Set MenuItem = SDB.UI.AddMenuItem(SDB.UI.Menu_Scripts, 0, -1)
MenuItem.Caption = ScriptCaption
MenuItem.Hint = ScriptHint
MenuItem.IconIndex = 25
MenuItem.ShortCut = ScriptShortCut
Script.RegisterEvent MenuItem, "OnClick", ScriptName
Dim TBItem : Set TBItem = SDB.UI.AddMenuItem(SDB.UI.Menu_TbStandard, 0, -1)
TBItem.Caption = ScriptCaption
TBItem.Hint = ScriptHint
TBItem.IconIndex = 25
TBItem.ShortCut = ScriptShortCut
Script.RegisterEvent TBItem, "OnClick", ScriptName
End If
End Sub
Sub ExtractFields(MenuItem)
Set Form = CreateForm("Change tags based on existing tags", 100, 100, 495, 140, bsDialog, poScreenCenter, True, "ExtractFields_Form")
Set SDB.Objects("ExtractFields_Form") = Form
Call CreateLabel(Form, "Enabled", 7, 15, 50, 20)
Call CreateLabel(Form, "Field name", 85, 15, 60, 20)
Call CreateLabel(Form, "Mask to recognise or tag", 280, 15, 120, 20)
Set lblSpin = CreateLabel(Form, "Entry lines # :", 20, 0, 70, 20)
Set SpinEdit = CreateSpinEdit(Form, 95, 0, 50, 20, "SpinEdit")
SpinEdit.MinValue = 1
SpinEdit.MaxValue = 15
SpinEdit.Value = def_EntryLinesCnt
Set btnSpin = CreateButton(Form, "Show", 150, 0, 50, 20, "btnSpin_OnClick")
Set lblPemTag = CreateLabel(Form, "Entry parsing method :", 265, 0, 130, 20)
Set lblPemValue = CreateLabel(Form, " ", 380, 0, 50, 20)
lblPemValue.Caption = "Serial"
ParseEntryMethod = pemSerial
Set btnPem = CreateButton(Form, "Switch", 420, 0, 50, 20, "btnPem_OnClick")
Set btnExtractFields = CreateButton(Form, "Extract Fields", 90, 0, 150, 20, "btnExtractFields_OnClick")
btnExtractFields.Default = True
Set btnClose = CreateButton(Form, "Close", 252, 0, 150, 20, "btnClose_OnClick")
btnClose.Cancel = True
Set lblMasks = CreateLabel(Form, "Usable mask fields :", 20, 0, 90, 20)
Set edtMasks = CreateLabel(Form, SDB.Tools.Mask2UFText(ArrayToString(CommonTags, ", ")), 120, 0, 350, 50)
edtMasks.Multiline = True
NumberOfEntryLines = 0
Call ChangeNumberOfEntryLines(def_EntryLinesCnt)
Call SelectDropDownText(DataFieldsArray(0), def_TagField)
MaskTextArray(0).Text = SDB.Tools.Mask2UFText(def_TagMask)
EnableStateArray(0).Checked = True
Form.Common.Visible = True
End Sub
Sub ChangeNumberOfEntryLines(NewNumber)
Form.Common.Height = 200 + NewNumber * 25
lblMasks.Common.Top = Form.Common.Height - 145
edtMasks.Common.Top = Form.Common.Height - 158
lblSpin.Common.Top = Form.Common.Height - 101
SpinEdit.Common.Top = Form.Common.Height - 105
lblPemTag.Common.Top = Form.Common.Height - 101
lblPemValue.Common.Top = Form.Common.Height - 101
btnPem.Common.Top = Form.Common.Height - 105
btnSpin.Common.Top = Form.Common.Height - 105
btnExtractFields.Common.Top = Form.Common.Height - 65
btnClose.Common.Top = Form.Common.Height - 65
Dim i
If NewNumber < NumberOfEntryLines Then
For i = NewNumber To NumberOfEntryLines - 1
EnableStateArray(i).Common.Visible = False
DataFieldsArray(i).Common.Visible = False
MaskTextArray(i).Common.Visible = False
DirectionArray(i).Common.Visible = False
Next
ReDim Preserve EnableStateArray(NewNumber - 1)
ReDim Preserve DataFieldsArray(NewNumber - 1)
ReDim Preserve MaskTextArray(NewNumber - 1)
ReDim Preserve DirectionArray(NewNumber - 1)
Else
ReDim Preserve EnableStateArray(NewNumber - 1)
ReDim Preserve DataFieldsArray(NewNumber - 1)
ReDim Preserve MaskTextArray(NewNumber - 1)
ReDim Preserve DirectionArray(NewNumber - 1)
For i = NumberOfEntryLines To NewNumber - 1
Dim chkEnabled : Set chkEnabled = CreateCheckBox(Form, " ", 20, 10 + 25*(i+1), 15, 20, "chkEnabled" & i)
Dim ddnDataFields : Set ddnDataFields = CreateDropDown(Form, 55, 10 + 25*(i+1), 130, 20, "ddnDataFields" & i)
ddnDataFields.Style = csDropDownList
Call FillDropDownFromArray(ddnDataFields, SongDataFields)
Dim btnChangeDirection : Set btnChangeDirection = CreateButton(Form, "-->", 192, 10 + 25*(i+1), 40, 20, "btnChangeDirection_OnClick")
btnChangeDirection.Common.ControlName = "btnChangeDirection" & i
Dim edtMaskText : Set edtMaskText = CreateEdit(Form, "", 240, 10 + 25*(i+1), 230, 15, "edtMaskText" & i)
Set EnableStateArray(i) = chkEnabled
Set DataFieldsArray(i) = ddnDataFields
Set MaskTextArray(i) = edtMaskText
Set DirectionArray(i) = btnChangeDirection
Next
End If
NumberOfEntryLines = NewNumber
' Stupid, but the only way to get a redraw of the form (and so get correct displaying of the newly added controls)
Form.Common.Visible = False
Form.Common.Visible = True
End Sub
'*****************************************************
'**** EVENT HANDLING METHODS ****
'*****************************************************
Sub btnChangeDirection_OnClick(Button)
If Button.Caption = "-->" Then
Button.Caption = "<--"
Else
Button.Caption = "-->"
End If
End Sub
Sub btnPem_OnClick(btnPem)
If ParseEntryMethod = pemSerial Then
lblPemValue.Caption = "Parallel"
ParseEntryMethod = pemParallel
Else
lblPemValue.Caption = "Serial"
ParseEntryMethod = pemSerial
End If
End Sub
Sub btnSpin_OnClick(btnSpin)
Call ChangeNumberOfEntryLines(SpinEdit.Value)
End Sub
Sub btnClose_OnClick(btnClose)
Form.Common.Visible = False
Set Form = Nothing
End Sub
Sub btnExtractFields_OnClick(btnExtractFields)
Dim SongList : Set SongList = SDB.CurrentSongList
Dim Progress : Set Progress = SDB.Progress
Progress.Text = SDB.Localize("Extracting and applying field information...")
Progress.MaxValue = SongList.Count
Dim i, j, Song, SongOrig, MaskTextInternal
For i = 0 To SongList.Count - 1
Progress.Text = SDB.Localize("Extracting and applying field information... (Track " & (i+1) & " of " & SongList.Count & ")")
Set Song = SongList.Item(i)
Set SongOrig = Song.GetCopy
'Song.ArtistName = ""
'Song.AlbumArtistName = ""
For j = 0 To UBound(EnableStateArray)
If EnableStateArray(j).Checked = True Then
If DirectionArray(j).Caption = "-->" Then
MaskTextInternal = SDB.Tools.UFText2Mask(MaskTextArray(j).Text)
If ParseEntryMethod = pemSerial Then
Execute("Call Song.ParseText(Song." & DataFieldsArray(j).Text & ", MaskTextInternal)")
Else 'ParseEntryMethod = pemParallel
Execute("Call Song.ParseText(SongOrig." & DataFieldsArray(j).Text & ", MaskTextInternal)")
End If
Else
MaskTextInternal = SDB.Tools.UFText2Mask(MaskTextArray(j).Text)
If ParseEntryMethod = pemSerial Then
Execute("Song." & DataFieldsArray(j).Text & " = Fillin(Song, MaskTextInternal)")
Else 'ParseEntryMethod = pemParallel
Execute("Song." & DataFieldsArray(j).Text & " = Fillin(SongOrig, MaskTextInternal)")
End If
End If
End If
Next
'If Song.ArtistName = "" Then Song.ArtistName = SongOrig.ArtistName
'If Song.AlbumArtistName = "" Then Song.AlbumArtistName = SongOrig.AlbumArtistName
Progress.Value = i + 1
Song.UpdateAlbum
Song.UpdateArtist
Song.UpdateDB
Next
Call SongList.UpdateAll
End Sub
Function Fillin(Song, MaskTextInternal)
Fillin = MaskTextInternal
Dim key
For Each key In FieldDict.Keys
Call Execute("Fillin = Replace(Fillin, key, CStr(Song." & FieldDict(key) & "), 1, -1, 1)")
Next
End Function
Function ArrayToString(SourceArray, SepChar)
ArrayToString = SourceArray(0)
Dim i
For i = 1 To UBound(SourceArray)
ArrayToString = ArrayToString & SepChar & SourceArray(i)
Next
End Function
'*****************************************************
'**** CONTROLS UTILITY METHODS ****
'*****************************************************
' BorderStyle constants
const bsNone = 0 'No border
const bsSizeable = 2 'Standard window (resizable)
const bsDialog = 3 'Dialog window (not resizable)
const bsToolWindow = 4 'Toolwindow (not resizable)
const bsSizeToolWin = 5 'Toolwindow (resizable)
' Position constants (for Forms)
const poDesigned = 0 'Position and size specified by Left, Top, Width and Height
const poDefault = 1 'Position and size determined by the operating system
const poScreenCenter = 4 'Centered on the screen
' DropDown Style constants
Const csDropDown = 0 'DropDown can be edited
Const csDropDownList = 2 'DropDown cannot be edited (user can only select from a list of values)
Function CreateForm(Caption, X, Y, Width, Height, BorderStyle, FormPosition, StayOnTop, SavePositionName)
Set CreateForm = SDB.UI.NewForm
CreateForm.Caption = Caption
CreateForm.Common.SetRect X, Y, Width, Height
CreateForm.BorderStyle = BorderStyle
CreateForm.FormPosition = FormPosition
CreateForm.StayOnTop = StayOnTop
CreateForm.SavePositionName = SavePositionName
End Function
Function CreateDropDown(Owner, X, Y, Width, Height, ControlName)
Set CreateDropDown = SDB.UI.NewDropDown(Owner)
CreateDropDown.Common.SetRect X, Y, Width, Height
CreateDropDown.Common.ControlName = ControlName
End Function
Function CreateEdit(Owner, Text, X, Y, Width, Height, ControlName)
Set CreateEdit = SDB.UI.NewEdit(Owner)
CreateEdit.Text = Text
CreateEdit.Common.SetRect X, Y, Width, Height
CreateEdit.Common.ControlName = ControlName
End Function
Function CreateSpinEdit(Owner, X, Y, Width, Height, ControlName)
Set CreateSpinEdit = SDB.UI.NewSpinEdit(Owner)
CreateSpinEdit.Common.SetRect X, Y, Width, Height
CreateSpinEdit.Common.ControlName = ControlName
End Function
Function CreateButton(Owner, Caption, X, Y, Width, Height, OnClickHandler)
Set CreateButton = SDB.UI.NewButton(Owner)
CreateButton.Caption = Caption
CreateButton.Common.SetRect X, Y, Width, Height
If OnClickHandler <> "" Then
Script.RegisterEvent CreateButton.Common, "OnClick", OnClickHandler
End If
End Function
Function CreateLabel(Owner, Caption, X, Y, Width, Height)
Set CreateLabel = SDB.UI.NewLabel(Owner)
CreateLabel.Caption = Caption
CreateLabel.Common.SetRect X, Y, Width, Height
End Function
Function CreateCheckBox(Owner, Caption, X, Y, Width, Height, ControlName)
Set CreateCheckBox = SDB.UI.NewCheckBox(Owner)
CreateCheckBox.Caption = Caption
CreateCheckBox.Common.SetRect X, Y, Width, Height
CreateCheckBox.Common.ControlName = ControlName
End Function
Sub SelectDropDownText(DropDown, Text)
Dim i
For i = 0 To DropDown.ItemCount - 1
If DropDown.ItemText(i) = Text Then
DropDown.ItemIndex = i
DropDown.Text = Text
Exit For
End If
Next
End Sub
Sub FillDropDownFromArray(DropDown, SourceArray)
Dim i
For i = 0 To UBound(SourceArray)
DropDown.AddItem SourceArray(i)
Next
End Sub
'*****************************************************
'**** EXTRA ENUMERATIONS ****
'*****************************************************
Dim CommonTags : CommonTags = Array("%A", "%L", "%S", "%G", "%T", "%Y", "%X", "%R", "%C", "%M", "%B", "%U", "%V", "%W", "%P", "%F")
' Enumeration of the most important fields in the SongData object
Dim SongDataFields : SongDataFields = Array( _
"AlbumArtistName", _
"AlbumName", _
"ArtistName", _
"Author", _
"Band", _
"Bitrate", _
"BPM", _
"Comment", _
"Conductor", _
"Copyright", _
"Custom1", _
"Custom2", _
"Custom3", _
"Encoder", _
"Genre", _
"InvolvedPeople", _
"Lyricist", _
"Lyrics", _
"MediaLabel", _
"Mood", _
"MusicComposer", _
"Occasion", _
"OriginalArtist", _
"OriginalLyricist", _
"OriginalTitle", _
"OriginalYear", _
"Publisher", _
"Quality", _
"Rating", _
"Tempo", _
"Title", _
"TrackOrder", _
"Year")
Dim FieldDict : Set FieldDict = CreateObject("Scripting.Dictionary")
With FieldDict
.Add "%A", "ArtistName"
.Add "%C", "Author"
.Add "%G", "Genre"
.Add "%L", "AlbumName"
.Add "%M", "BPM"
.Add "%R", "AlbumArtistName"
.Add "%S", "Title"
.Add "%T", "TrackOrder"
.Add "%U", "Custom1"
.Add "%V", "Custom2"
.Add "%W", "Custom3"
.Add "%Y", "Year"
.Add "%P", "Path"
End With
Information:
By default, the script starts with a mask that works the same way as the script "Split Artist Title" works. (to split "Artist - Title" titles received from FreeDB).
![Image](http://home.scarlet.be/ruben.castelein/MM/ExtractFields2.gif)
You can specify the number of "entry lines" you want to display. Each entry line is used to parse the track information field (from the dropdown) and save the matching information to other (or even the same) track information fields (from the mask). Each entry line can be enabled.
When you are using more than one entry line, the parsing can happen in two ways:
- Serial: each entry line is parsed after each other, so the second line parses the song that has already been changed by the first line.
- Parallel: each entry line parses with the same beginning information, so it doesn't depend on the previous entry lines.
Example 1: Serial vs. Parallel
Title = My Song Title
ArtistName = My Artist Name
entry line 1: On Title With mask <Artist>
entry line 2: On ArtistName With mask <Title>
Serial:
- entry line 1 copies the contents of (the previous = original) Title "My Song Title" to ArtistName
- entry line 2 copies the contents of (the previous = already changed) ArtistName "My Song Title" to Title
---> Title = My Song Title
---> ArtistName = My Song Title
Parallel:
- entry line 1 copies the contents of (the original) Title "My Song Title" to Artist(Name)
- entry line 2 copies the contents of (the original) ArtistName "My Artist Name" to Title
---> Title = My Artist Name
---> ArtistName = My Song Title
--> So the "parallel" way lets you e.g. easily switch fields (as replacement of the SwapArtistTitle and SwitchOrCopyFields (in "switch" mode) scripts).
With only the one line like this, the script acts as the SwitchOrCopyFields script (in "copy" mode).
Example 2: Remove leading text
If you have a Title like "DragonMegaStore @ MyTitle" and want to change it to "MyTitle", then use one entry line:
entry line 1: On Title With mask <Skip> @ <Title>