Code: Select all
' =========================================================================
' WebSearch Panels
'
' This script adds as many panels as defined to the MediaMonkey interface.
' Each panel performs a specific web search on Artist, Title or Album.
'
' The script needs a XML file as a configuration file.
'
' The script is discussed in in the Forum at the MediaMonkey homepage at
' http://www.mediamonkey.com/forum/viewtopic.php?t=11254
'
' Script by jn
' Last modified by gege in 2007-02-24
'
' Changelog:
' ----------
'
' Version 2007-02-24:
'
' - Fixed: a bug in PanelToComment procedure. NewLyrics variable was referenced
' instead of NewComment.
'
' - Fixed: UpdateDB and WriteTags methods are invoked after assining new text
' to Lyrics or Comment fields, in PanelToLyrics and PanelToComment procedures.
' This is necessary, so the information is permanently written to the Db and the Tag.
'
' - Modified: all the text strings declared as constants in the begginig of the
' script, for easier localization.
'
' - Modified: WebSearch.XML file moved to %MMhome%\Scripts\Auto folder, as I prefer
' it staying close to its dad. Also added an option to easily change this.
'
' - Added: option to choose buttons placement. I prefer then at bottom.
'
' - Added: TextCleanUp function, to make some very basic text clean-up, before it is
' saved to lyrics or comments. Needs improvement. There's also an option to disable this.
'
' - Added: GetTextFromClipboard function. When there's nothing selected in current panel,
' it gets the text from the clipboard. Useful when the text you want to paste in lyrics
' or comments field is outside the panel, like a TXT file, for instance. All you need is
' select and copy (CTRL+C) that text and then press Lyrics or Comment button.
'
' - ToDo: Add tooltip Hints to the buttons (that "?" isn't very explanatory, at all), but
' I suspect that buttons don't support hints...
'
' =========================================================================
' -------------------------------------------------------------------------
' Make sure all variables are declared
Option Explicit
Const ObjectName = "WebSearch_Panels"
Const optionXmlPath = "\Scripts\Auto\WebSearch.xml"
Const optionToolbarAlign = 2 ' 1=top 2=bottom 3=left 4=right
Const optionDoTextCleanUp = 1 ' 1=yes 0=no
' Localizable strings
Const stringsMenuCaption = "Search the web"
Const stringsMenuHint = "Search the Web for information about current song or artist!"
Const stringsMsgOverwriteLyrics = "Overwrite existing Lyrics?"
Const stringsMsgOverwriteComment = "Overwrite existing Comment?"
Const stringsLyricsBtn = "Lyrics"
Const stringsLyricsHint = "Saves current selection or clipboard content to Lyrics field in ID3 tag." 'Not used yet
Const stringsCommentBtn = "Comment"
Const stringsCommentHint = "Saves current selection or clipboard content to Comment field in ID3 tag." 'Not used yet
' -------------------------------------------------------------------------
' This is the main start function that is executed when MM starts
Sub OnStartup
Dim Items
' Create a menu anchor in the search toolbar
Dim Menu
Set Menu = SDB.UI.AddMenuItemSub(SDB.UI.Menu_TbSearch, 0, 0)
With menu
.Caption = stringsMenuCaption
.Hint = stringsMenuHint
End With
' Create the Panels
Set Items = GetWebSearchItems
With Items
.ReadFile SDB.ApplicationPath & optionXmlPath
.CreatePanels
.CreateMenus(Menu)
End With
' Save them for later use
Set SDB.Objects(ObjectName) = Items
' Listen for changes
Script.RegisterEvent SDB, "OnPlay", "PanelInfom"
End Sub
' -------------------------------------------------------------------------
' Just for convenience: Returns the instance of WebSearchItems we need.
Function GetWebSearchItems
If SDB.Objects(ObjectName) Is Nothing Then
Set GetWebSearchItems = New WebSearchItems
Else
Set GetWebSearchItems = SDB.Objects(ObjectName)
End If
End Function
' -------------------------------------------------------------------------
' Handler Routines
'
' These Handlers only call the Methods on the current Panel Object.
' They are fired by events like menu clicks, panel closure etc.
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' PanelToggle is called whenever a panel is closed or opened (by menu or by X)
Sub PanelToggle(ByVal Item)
GetWebSearchItems.PanelSearch(Item).Toggle
End Sub
' -------------------------------------------------------------------------
' PanelClose is called whenever a Panel is closed
' (we can't use PanelToggle for this, because it is already closed when the
' function is called)
Sub PanelClose(ByVal Item)
GetWebSearchItems.PanelSearch(Item).Close
End Sub
' -------------------------------------------------------------------------
' PanelGoForward is called whenever a forward button is klicked
Sub PanelGoForward(ByVal Item)
GetWebSearchItems.PanelSearch(Item).GoForward
End Sub
' -------------------------------------------------------------------------
' PanelGoBack is called whenever a back button is klicked
Sub PanelGoBack(ByVal Item)
GetWebSearchItems.PanelSearch(Item).GoBack
End Sub
' -------------------------------------------------------------------------
' PanelGoSearch is called whenever a home button is klicked
Sub PanelGoSearch(ByVal Item)
GetWebSearchItems.PanelSearch(Item).GoSearch
End Sub
' -------------------------------------------------------------------------
' OnPlayChange is called whenever a new title is played
' It and informs all panels about the new title
Sub PanelInfom
GetWebSearchItems.Inform
End Sub
' -------------------------------------------------------------------------
' TextCleanUp is used... (guess what) to clean-up the text before it is
' saved to lyrics or comments field.
' For now it is very primitive and does only basic replacements.
' I'd like to be able to do more complex operations like capitalising
' sentences (useful for those lyrics all in lowercase or, even worse, all
' in uppercase). Maybe this can be achieved using regular expressions...
' (function added by gege)
Function TextCleanUp (Text)
If optionDoTextCleanUp = 1 Then
' Let's get rid of those double/triple empty lines...
Text=Replace(Text,vbnewline&vbnewline&vbnewline, vbnewline&vbnewline)
Text=Replace(Text,vbnewline&vbnewline&vbnewline, vbnewline&vbnewline)
' And now we correct some common punctuation problems
Text=Replace(Text," ?","?")
Text=Replace(Text," !","!")
Text=Replace(Text," ,",",")
Text=Replace(Text," :",":")
Text=Replace(Text,"…","...")
Text=Replace(Text," ...","...")
Text=Replace(Text,"‘","'")
Text=Replace(Text,"’","'")
Text=Replace(Text,"´","'")
' Capitalised it's much better...
Text=Replace(Text," i "," I ")
Text=Replace(Text," i'm "," I'm ")
Text=Replace(Text," i'd "," I'd ")
Text=Replace(Text," i'll "," I'll ")
Text=Replace(Text," i've "," I've ")
Text=Replace(Text," ok "," OK ")
Text=Replace(Text," tv "," TV ")
Text=Replace(Text," dj "," DJ ")
' Let's get things appart...
Text=Replace(Text," youre "," you're")
Text=Replace(Text," youve "," you've")
Text=Replace(Text," dont "," don't ")
Text=Replace(Text," cant "," can't ")
Text=Replace(Text," aint "," ain't ")
Text=Replace(Text," didnt "," didn't ")
Text=Replace(Text," wasnt "," wasn't ")
Text=Replace(Text," isnt "," isn't ")
Text=Replace(Text," wont "," won't ")
Text=Replace(Text," wouldnt "," wouldn't ")
Text=Replace(Text," shouldnt "," shouldn't ")
Text=Replace(Text," havent "," haven't ")
End If
TextCleanUp = Text
End Function
' -------------------------------------------------------------------------
' Returns the current text content of clipboard. I looked at the forums and
' it looks like there isn't a more elegant way to do this (I mean without
' instantiating IE).
' This is useful when the text you want to paste in lyrics or comments field
' is outside the panel, like a TXT file, for instance. All you need is
' select and CTRL+C in that text...
' (function added by gege)
Function GetTextFromClipboard
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate("about:blank")
GetTextFromClipboard = IE.Document.ParentWindow.ClipBoardData.GetData("text")
IE.Quit
Set IE=Nothing
End Function
' -------------------------------------------------------------------------
' PanelToLyrics is called whenever the lyrics button is clicked
Sub PanelToLyrics(ByVal Item)
Dim NewLyrics
NewLyrics = GetWebSearchItems.PanelSearch(Item).Selection
If Len(NewLyrics) = 0 Then
' If there's nothing selected in current panel, let's try the clipboard...
NewLyrics = GetTextFromClipboard
End If
If Len(NewLyrics) > 10 Then
With SDB.Player.CurrentSong
If Len(.Lyrics) = 0 Then
.Lyrics = TextCleanUp(NewLyrics)
.UpdateDB
.WriteTags
Elseif MsgBox(stringsMsgOverwriteLyrics, vbYesNo) = vbYes Then
.Lyrics = TextCleanUp(NewLyrics)
.UpdateDB
.WriteTags
End If
End With
End If
End Sub
' -------------------------------------------------------------------------
' PanelToComment is called whenever the comments button is klicked
Sub PanelToComment(ByVal Item)
Dim NewComment
NewComment = GetWebSearchItems.PanelSearch(Item).Selection
If Len(NewComment) = 0 Then
' If there's nothing selected in current panel, let's try the clipboard...
NewComment = GetTextFromClipboard
End If
If Len(NewComment) > 10 Then
With SDB.Player.CurrentSong
If Len(.Comment) = 0 Then
.Comment = TextCleanUp(NewComment)
.UpdateDB
.WriteTags
Elseif MsgBox(stringsMsgOverwriteComment, vbYesNo) = vbYes Then
.Comment = TextCleanUp(NewComment)
.UpdateDB
.WriteTags
End If
End With
End If
End Sub
' -------------------------------------------------------------------------
' The WebSearchItem class
' -------------------------------------------------------------------------
Class WebSearchItem
Public Name
Public Caption
Public Description
Public Start
Public SearchURL
Private Panel
Private Menuitem
Private Browser
' Buttons
Private btnGoBack
Private btnGoForward
Private btnGoSearch
Private btnLyrics
Private btnComment
' -------------------------------------------------------------------------
' Add a Panel for the WebSearchItem
Sub CreatePanel
Dim UI
Set UI = SDB.UI
Set Panel = UI.NewDockablePersistentPanel(Name)
With Panel
If Panel.IsNew then
.DockedTo = 2
.Common.Width = 250
.Common.Visible = true
End If
.Caption = Caption
End With
Script.RegisterEvent Panel, "OnClose", "PanelClose"
' Create a web browser component
Set Browser = UI.NewActiveX(Panel, "Shell.Explorer")
With Browser
.Common.Align = 5 ' Fill all client rectangle
.Interf.Navigate Start
End With
' Navigation Bar
Dim Nav
Set Nav = UI.NewPanel(Panel)
With Nav.Common
.Align = optionToolbarAlign
.Height = 35
End With
' Back button
Set btnGoBack = UI.NewButton(Nav)
With btnGoBack
.Common.SetRect 5, 5, 25, 25
.Caption = "<"
.UseScript = Script.ScriptPath
.OnClickFunc = "PanelGoBack"
End With
' Forward button
Set btnGoForward = UI.NewButton(Nav)
With btnGoForward
.Common.SetRect 35, 5, 25, 25
.Caption = ">"
.UseScript = Script.ScriptPath
.OnClickFunc = "PanelGoForward"
End With
' Search button
Set btnGoSearch = UI.NewButton(Nav)
With btnGoSearch
.Common.SetRect 65, 5, 25, 25
.Caption = "?"
.UseScript = Script.ScriptPath
.OnClickFunc = "PanelGoSearch"
End With
' Search button
Set btnLyrics = UI.NewButton(Nav)
With btnLyrics
.Common.SetRect 95, 5, 75, 25
.Caption = stringsLyricsBtn
.UseScript = Script.ScriptPath
.OnClickFunc = "PanelToLyrics"
End With
' Search button
Set btnComment = UI.NewButton(Nav)
With btnComment
.Common.SetRect 175, 5, 75, 25
.Caption = stringsCommentBtn
.UseScript = Script.ScriptPath
.OnClickFunc = "PanelToComment"
End With
End Sub
' -------------------------------------------------------------------------
' Add a menu item for the WebSearchItem
Sub CreateMenu(ByVal Parent)
Set Menuitem = SDB.UI.AddMenuItem(Parent, 0, 0)
With Menuitem
.Caption = Caption
.Checked = Panel.Common.Visible
.IconIndex = 55
.Hint = Description
End With
Script.RegisterEvent Menuitem, "OnClick", "PanelToggle"
End Sub
' -------------------------------------------------------------------------
' Go to the respective page
Sub GoSearch
Browser.Interf.Navigate(ReplaceTokens(SearchURL, SDB.Player.CurrentSong))
End Sub
' -------------------------------------------------------------------------
' Go forward one page
Sub GoForward
'I've found no better way to find out if navigation is possible...
On Error Resume Next
Browser.Interf.GoForward
End Sub
' -------------------------------------------------------------------------
' Go back one page
Sub GoBack
On Error Resume Next
Browser.Interf.GoBack
End Sub
' -------------------------------------------------------------------------
' Switch from visible to invisible or the other way
Sub Toggle
Panel.Common.Visible = not Panel.Common.Visible
Menuitem.Checked = Panel.Common.Visible
End Sub
' -------------------------------------------------------------------------
' Close a panel
Sub Close
Menuitem.Checked = false
End Sub
' -------------------------------------------------------------------------
' Returns the selected text in a browser
Public Property Get Selection
Selection = Browser.Interf.document.selection.createRange.text
End Property
' -------------------------------------------------------------------------
' Returns the Panel's visibility
Public Property Get Visible
Visible = Panel.Common.Visible
End Property
' -------------------------------------------------------------------------
' Replace tokens in the URL.
Function ReplaceTokens(ByVal URL, ByVal Song)
With Song
URL = Replace(URL, "%artist%", .ArtistName)
URL = Replace(URL, "%title%", .Title)
URL = Replace(URL, "%album%", .AlbumName)
URL = Replace(URL, "%albumartist%", .AlbumArtistName)
End With
ReplaceTokens = URL
End Function
End Class
' -------------------------------------------------------------------------
' The WebSearchItems class
' -------------------------------------------------------------------------
Class WebSearchItems
Public Panels
' -------------------------------------------------------------------------
' Clears the current collection and creates Panels as defined in a
' configuration file
Sub ReadFile(ByVal XMLFile)
' The configuration file
Dim XMLDoc
' For the config file's root object
Dim Root
' One config file's entry
Dim Site
' One config file's details
Dim config
' One panel
Dim Panel
' Read the Configuration File
set XMLDoc = CreateObject("Microsoft.XMLDOM")
With XMLDoc
.async = "false"
.load XMLFile
Set Root = .selectNodes("configuration")
End With
Set XMLDoc = Nothing
Set Panels = CreateObject("Scripting.Dictionary")
' We now create the Panels, adding them to the Dictionary object for later
' retrieval
For Each Site In Root(0).childNodes
Set Panel = New WebSearchItem
With Panel
For Each config In Site.childNodes
if config.baseName = "name" then .Name = config.Text
if config.baseName = "caption" then .Caption = config.Text
if config.baseName = "description" then .Description = config.Text
if config.baseName = "start" then .Start = config.Text
if config.baseName = "url" then .SearchURL = config.Text
Next
Panels.Add .Name, Panel
End With
Next
Set Root = Nothing
End Sub
' -------------------------------------------------------------------------
' Saves the configuration to a file
Sub SaveFile(ByVal XMLFile)
' The configuration file
Dim XMLDoc
' For the config file's root object
Dim Root
' For one site
Dim Site
' For a config entry
Dim config
Set XMLDoc = CreateObject("Microsoft.XMLDOM")
Set Root = XMLDoc.CreateNode(1, "configuration", "")
Dim Key
For Each Key in Panels
Set Site = XMLDoc.CreateNode(1, "site", "")
Set config = XMLDoc.CreateNode(1, "name", "")
config.text =Panels(Key).Name
Site.AppendChild config
Set config = XMLDoc.CreateNode(1, "caption", "")
config.text =Panels(Key).Caption
Site.AppendChild config
Set config = XMLDoc.CreateNode(1, "description", "")
config.text =Panels(Key).Description
Site.AppendChild config
Set config = XMLDoc.CreateNode(1, "start", "")
config.text =Panels(Key).Start
Site.AppendChild config
Set config = XMLDoc.CreateNode(1, "url", "")
config.text =Panels(Key).SearchURL
Site.AppendChild config
Root.AppendChild Site
Next
Dim PI
Set PI = XMLDoc.createProcessingInstruction("xml", " version = ""1.0""")
XMLDoc.AppendChild PI
XMLDoc.AppendChild Root
XMLDoc.Save(XMLFile)
End Sub
' -------------------------------------------------------------------------
' Show the panels
Sub CreatePanels
Dim Key
For Each Key in Panels
Panels(Key).CreatePanel
Next
End Sub
' -------------------------------------------------------------------------
' Add the menu items. The parameter mus be a SDBUI.Submenu object.
' By calling this method multiple times, it *might* be possible to create
' more than one menu structure?
Sub CreateMenus(RootMenu)
Dim Key
For Each Key in Panels
Panels(Key).CreateMenu(RootMenu)
Next
End Sub
' -------------------------------------------------------------------------
' Inform all panels about the new title
Sub Inform
Dim Key
For Each Key in Panels
Panels(Key).GoSearch
Next
End Sub
' -------------------------------------------------------------------------
' This helper function returns one WebSearchItem by the "Item".
' The "Item" can be a panel object, a menu object etc.
Function PanelSearch(ByVal Item)
Dim Key
Select Case TypeName(Item)
Case "SDBUIDockablePanel"
' The Panel object has a naming property that is the same as the
' index in our Dictionary, so it's easy in this case
Set PanelSearch = Panels(Item.Common.ControlName)
Exit Function
Case "SDBMenuItem"
' Unfortunately, Menuitem objects don't have such a naming property.
' Therefore, we have to search for the caption. This is the reason
' that the captions have to be unique.
For Each Key in Panels
If Panels(Key).Caption = Item.Caption Then
Set PanelSearch = Panels(Key)
Exit Function
End If
Next
Case "SDBUIButton"
' A bit complicated: The Panel is the Button's grand-parent
Key = Item.Common.Parent.Common.Parent.Common.ControlName
Set PanelSearch = Panels(Key)
Exit Function
End Select
End Function
End Class