DUPPY CONQUEROR script (MM4 2016)

Download and get help for different MediaMonkey Addons.

Moderators: Peke, Gurus

Just Guessing
Posts: 64
Joined: Mon Sep 03, 2012 12:06 pm

DUPPY CONQUEROR script (MM4 2016)

Post by Just Guessing » Tue Aug 30, 2016 3:37 pm

DUPPY CONQUEROR v4.dave
***v4 updated 9/8/2016

This script is designed to offer side by side graphic and sonic comparisons of duplicate (and seemingly duplicate) music tracks, in a floating MediaMonkey form.

Image

I offer this script not so much as a finished product, but as a starting place; because it is HIGHLY personalized for the way I organize/tag etc. You will probably have to get hands dirty tweaking the code to suit your monitor and tag usage. For example, The form generated is BIG (1845x1130). If you're working on a smaller monitor, you will have to tweak plenty of numbers.

----------------------------------------- USEAGE:
Start a song and open the form. The form has an upper panel (with overall controls) and a dynamic lower panel with listing of duplicate tracks of the current song (from the MM database). The determination of duplicates is a compromise of speed vs accuracy, but some manipulators are in the top panel to help adjust results. Preview the tracks and/or make decisions on the best version, delete the rest if desired, migrate tags/artwork, or change tags - as desired.

For more serious use, drag track/tracks for consideration to a PLAYLIST titled 'Duppy'. Open the playlist and start the top song in the playlist. Then use 'NEXT TRACK' or 'NEXT DUP SET' to work within the form, through the tracks in the 'Duppy' playlist. The buttons 'NEXT TRACK' or 'NEXT DUP SET' work ONLY from a playlist titled 'Duppy'. The 'Duppy' playlist does NOT need to have all the duplicates in it, just one will do, if titles are roughly the same. [If several duplicate files ARE in the playlist, it is not a problem, BUT they should be ORGANIZED BY TITLE, or the built in design to delete them from the playlist when done will not scrub them all, and you'll have them reappear as you work through the playlist tracks. It REALLY helps to sort by artist/title BEFORE dragging to 'Duppy' playlist, as then they ~default~ to the best organization for workflow. ]

The script is designed to alter tags, and it is designed to DELETE MUSIC FILES FROM THE COMPUTER. As always, working with some backup is adviseable, till its crystal clear the results are definitely going to be as expected.

As written, the tag MERGE buttons are not going to change any tags (for safety); look at the top of the code to 'turn them on', when you understand what they'll do.

----------------------------------------- THE TOP PANEL (overall controls):
left side:
Image
  • 'INCLUDE TITLE?/ARTIST?' used to add track titles/artists that you wish to also appear (say wildly different spellings or mislabeled track that seems the same). Multiple items can be listed, separated by semi-colon. The ARTIST version seemed to be case sensitive (?) If so its an SQL thing, which I'll have to probe.
  • 'EXPAND TITLE' checkboxes will allow extra text that might appear to the left/to the right of the text of current song title (the 'TO THE RIGHT' checkbox is checked by default, note: they are not labeled). For the search, titles ignore apostrophes, commas, question-marks, and exclamation marks (hyphens are replaced with spaces). The default 'EXPAND TITLE right' default check may not be desirable if a song is too generic, like "Love" or something similar.
  • 'ANY ARTIST' could help with erroneous artist tags, but a song like 'Caravan' could give a hundred hits, so...
  • 'FUZZY MATCH' does a SOUNDEX sql search (used with 'ANY ARTIST' will likely result in out-of-control matches!)
  • 'ALLOW KARAOKE' - Tracks where genre=karaoke are not included by default..
Once one of the above manipulators is changed, press 'UPDATE' button in the top panel to refresh the list. The 'NEW LIST' button will undo any manipulator changes and start over with the currently playing song.

If you start another song from outside the form, tell the form with the 'NEW LIST' button.

right side:
Image

Once working from the form, the 'NEXT TRACK' button will remove the current tracks listed on the form from the top of the 'Duppy' playlist , start the next track in the playlist, and generate a listing for its duplicates. The 'NEXT DUP SET' button will plow ahead till a track in the playlist HAS DUPLICATES. This is great for working on a list of recently added songs which may or may NOT has dups.
  • 'MERGE ALL' is for track tags. If the best version is not the tagged version, this will transfer (merge together actually) MOOD/RATINGS/CUSTOM2/CUSTOM5/COMMENT/CONDUCTOR/DATE/TEMPO tags to the other tracks on the form. 'MERGE SELECTED' will merge only between tracks that are checked. (Some tags have a follow-up form to make you CHOOSE ONE OF MULTIPLE tags found, other tags allow multiple entries separated by semicolons. ***please see my details on the affected tags below!!***)
  • 'QUIT' is for closing the form.
----------------------------------------- the LOWER PANEL (the tracks):
left side:
Image
....A..........................B........................................................C.........................................D....................E....................F........................G.......
  • A = checkbox for marking track as 'selected'... 'REMOVE' will take track off the FORM (but not playlist, database or harddrive)... 'DELETE' will remove track FROM THE COMPUTER!!!! (there will be a confirmation page, unless somewhere else in windows/mediamonkey you've set something to prevent that)
  • B = Editboxes for TITLE, ARTIST, ALBUMARTIST. These editboxes provide a way to change these tags, after which you hit the track listing 'UPDATE' button, which writes the changes to the file! (edit box colors change to RED for unsaved edits)
  • C = 'UPDATE' button (affects ONLY that track and is done 1 track at a time)... 'MONO' button. ('MONO' appears only if track is flac and stereo. It writes the text ">(m)" to the Custom3 tag, so can be referenced later to delete half the file when it may have no value.)... Editboxes for GENRE, CONDUCTOR, ALBUM.
  • D = the length of track.
  • E = the channels: s=stereo, m=mono.
  • F = shows an exiting QUALITY tag.
  • G = The track bitrate (green=flac, yellow=high kbs mp3, red=low kbs mp3).

right side:
Image
........................A.................................B..............................C.....................................D.......................E.........
  • A = top line shows the existing tag CUSTOM3... Bottom line shows the existing tag COMMENTS.
  • B = PLAY buttons. Play2 is at 30 seconds, Play3 is at 45 seconds, 'Play1/2' goes to mid-track, and END gives the last few seconds... The "+/-" to the left are offset adjustments for the PLAY buttons to help with a precise examination when tracks have different intro silence, etc. Pink number shows current offset.
  • C = TOP BUTTON= existing GROUPING tag (***see my details on tags below!!***). Pressing this button will send the text to any other selected tracks GROUPING tag and send the track to a playlist with that name... Below that is the existing RATINGS TAG... Below that is the MOOD tag... Below that is CUSTOM2 tag. (These are affected by the MERGE buttons)
  • D = Existing artwork (embedded only)
  • E = 'FULL' button to see another form with full size version of the album art shown. You can leave that form open and press another tracks 'FULL' button too. (Must manually close that form ultimately)... Below that is the dimension of the art... '>SELECTED' will send the tracks album art to any selected tracks (DELETING ANY ART THE SELECTED TRACKS ALREADY HAD!!!)
----------------------------------------- MY TAGGING SYSTEM:
This how I use these tags and consequently, this is how this script handles these tags. Please tweak the daylights out of this script till it does things the way YOU like. Tweaking for tags would be to the sub MergeTracks(Btn) and the sub MakeTheEntries.
  • 'MultiTags' are tags which I allow to have multiple entries, seperated by semicolon/space
  • MOOD = (single tag) Used as PRIMARY emotional description of song
  • CUSTOM2 = (MultiTag) Using the same terminology as the MOOD but as a list, of secondary level descriptions.
  • RATINGS = ALMOST typical usage, but the script doesnt include ONE STAR ratings in the averaging of merged ratings (I use 1 star as a flag for attention not a rating -which can be entered on an old ipod, etc). And, sorry, I don't like half stars, please tweak the relevant section if you need it to behave differently.
  • COMMENT = (single tag) For general comments.
  • CONDUCTOR = (single tag) I use conductor as a secondary ALBUM name! Many times I'm not sure just what album is the source, or the true source isn't the same as the compilation the track came from. I kinda doubt anyone else is jumping onboard with this one, but I rely on it.
  • Custom4 = (single tag) SubGenre. (I hate a giant uncontrolled list of genres; my genre list is TIGHT and controlled. Subgenres is where more esoteric distinctions are made)
  • Custom3 = (MultiTag) Condition. Here I use a controlled list of abbreviations to describe the condition of the specific track. This is where this script writes ">(m)" to signify the desire to convert the stereo file to mono. You may say, why not use the QUALITY tag for that? ...because
  • QUALITY = (single tag) Source. CD is, well CD... etc. I even code which turntable I used to rip vinyl. VERY useful information to preserve.
  • ARTWORK: I try to have ONE piece of EMBEDDED album art. Very rarely have I regretted this. Folder art is not examined, and If you have tracks with multiple pieces of album art, i suggest trying to examine the script's relevant artwork code - it may not perform the way you like, or even give some error.
  • TEMPO = (single tag)
  • DATE = in a tag 'MERGE', the earliest date found is always selected.
  • GROUPING = (MultiTag) I use grouping as a place to track playlists the file is in. Several scripts I use to work with playlists have been tweaked to TRY to track this aspect (it gets inaccurate over time of course). But if you want a track in a playlist, took the time to put in there - it sucks to lose it from the playlist because you deleted the perhaps inferior version which WAS in the playlist. So my use of this button in the track's panel will give you a chance to keep your playlists filled with favorite music, provided the GROUPING tag is used to track this. One of the great script masters, BEX, has the PlaylistInMainWindow script designed to help do this.
----------------------------------------- TIPS:
  • There is no indicator on the form itself as to which track is playing (it would be simple to incorporate but could cause confusion if the mainwindow, nowplaying or player module was used to change tracks!), so its necessary to keep a mental note of which play button was just pressed.
  • I thinks its quite wise to always be playing the 'best version' when you start hitting 'delete' or 'remove' buttons. This makes it harder to delete the wrong track.
  • Remember that the auto-removal of tracks from thew 'Duppy' playlist (by use of 'NEXT TRACK'/'NEXT DUP SET' buttons) operate with regard to the TOP LISTED tracks in the playlist, so manually remove tracks from the playlist that are still at the top of 'Duppy' playlist, but have been dealt with already.
  • If you remove a song from the form erroneously, 'NEW LIST' button will recreate the original list of songs generated (minus any deletions made, of course).
  • Use taskmanager or whatever means to shut down MINILYRICS (or a similar large side script which is interacting with MM on every track advance. Helps with crashes and speed.
  • If PLAY buttons 'hang' when pressed, DONT PRESS THEM AGAIN (it will just hang twice); count to 2, give it it a moment.
  • If the script/form hangs, pressing buttons doesn't seem to help. Ppress windows 'X' close button on the form till closes. Mediamonkey will crash/close and need to be restarted.
  • To turn off/on script's behavior regarding clearing the NowPlaing window (default=cleared), change 'Const ClearNowPlaying = True' in top of the code.
----------------------------------------- BUGS & ISSUES:
  • 'UPDATE' buttons for track editboxes work about 50% of the time. I can NOT figure out why! But if they don't work the 1st time pressed, they WILL work the 2nd time pressed (but the changes are 'refreshed' back to original text). One CAN press 'UPDATE' BEFORE making editbox changes, but I found myself inclined to just gamble. But, if its more than just one paste of new text, you may want to 'update' one editbox first, so your extended efforts will 'stick' with less ensuing frustration.
  • CRASHES; On occasions Mediamonkey froze and had to shutdown. It seemed to be unrelated to anything specific, except just moving very fast through tracks. The 'auto-mode' saw this happen every 100 files or so. It may be something fixable, but may be more about MM and interaction with other scripts, or the OS. When screens froze, I pressed the FORM's windowclose 'X' button several times. MM then closes. Upon reopening, there were occasions where the DB didn't yet update a recent song deletion from the playlist. This gave a very scary message when I tried to start the file, that makes it sound like a TOTAL HARD-DRIVE WIPE-OUT! ... It is not... press 'cancel' on that scary message, remove the erroneously listed file listing via MM (from library & computer), and you can carry on.
  • a very irregular scenario saw the GROUPING tag (playlists) get a double entry, but it happened only once, and frankly I don't think most people are going to use that aspect anyway, so I haven't worried again about that issue.
  • I should put some error control in the script for trying to press 'NEXT TRACK'/'NEXT DUP SET' buttons when not currently viewing the 'Duppy' playlist...but I need a tip: how to test if the mainwindow is open to a particular playlist?
  • POSSIBLY A BIG DEAL!: I typically have filenames that are using a clean U.S. characterset (my long-used-yet-buggy filesystem explorer software gets cranky otherwise). In the script, filepaths are used for button control-names, BUT BUTTON CONTROL-NAMES GET CRANKY WITH SOME EXOTIC CHARACTERS. There is a function to replace these: ControlNameFromPath(). The function grows as I encounter an exotic character I haven't dealt with before. But for some users with more exotic filenames, they may get many error messages decribing that a control name isn't valid. You can either give up on this script, or add to the substitution-list function yourself. The bad characters can be replaced by anything valid; the idea is just to make a controlname that is going to be unique. If there's a vbscript function that more-or-less serves this purpose please enlighten me.
----------------------------------------- THE SCRIPT CODE:
Save below code to DuppyConqueror.vbs. The script is not an auto-script, so put in the root scripts folder and add the lines to the scripts.ini file (it is currently coded to launch from SHIFT/ALT/N hotkey):

[Duppy Conqueror]
FileName=DuppyConqueror.vbs
ProcName=DuppyConqueror
Order=10
DisplayName=Duppy Conqueror
Description=Compare Duplicates side by side
Language=VBScript
ScriptType=0
Shortcut=Shift+Alt+n

Code: Select all

'''''DuppyConqueror v4.dave'''''
Dim UI, TmpPath, Panel_1, Panel_2, DuppyForm, CurrentSong, SongList, SongListTmp
Dim MatchTitle, MatchTitleCore, MatchArtist, MatchGenre
Dim OneMood, OneSubGenre, OneTempo, OneConductor, OneRating, OneComment, DicFeelings, SelectionForm 
Dim DicOffset, Revision, AutoMode, QueryEmpty, SongCount

' change this once understand/adjust the MERGE sub & it's tag manipulations
Const ImReadyToAcceptResponsibilityForTagCode = False 

Const ClearNowPlaying = True ' this will clear NOW PLAYING list when you use NEXT buttons
Const FormHeight = 1130 ' taller is better, but can be adjusted
Const FormWidth = 1845 ' will require lots of button value changes if lowered
' whether ANY ARTIST and STAY IN GENRE checkboxes remain the way have them, for next song.
Const ArtistGenreAutocheck = False 

Sub DuppyConqueror
	if SDB.Player.CurrentSong Is Nothing Then : MsgBox "there's no CURRENT SONG!" : Exit Sub : End If	
	AutoMode = False
	Set UI = SDB.UI
	Set DicOffset = CreateObject("Scripting.Dictionary")
	TmpPath = CreateObject("WScript.Shell").ExpandEnvironmentStrings("%TEMP%") & "\"
	
	Set DuppyForm = UI.NewForm 
	DuppyForm.Common.SetRect 2, 2, FormWidth, FormHeight 
	DuppyForm.BorderStyle = 2  
	DuppyForm.FormPosition = 4 
	DuppyForm.SavePositionName = "DuppyAA" 
	DuppyForm.Caption = "Duppy Conqueror"
	DuppyForm.StayOnTop = False
	DuppyForm.Common.Visible = True 
	SDB.Objects("Duppy") = DuppyForm	
	
	Set Panel_1 = UI.NewGroupBox(DuppyForm) : Panel_1.Common.SetRect 5, 5, 1825, 40 
	
	MakeBUTTON Panel_1, 5,  5, 100, 30, "New List", "FreshSong", 10, "blue", "", ""
	MakeBUTTON Panel_1, 110,  5, 100, 30, "Update", "FreshSngList", 10, "blue", "", ""
	MakeEDITbx Panel_1, 220, 2, 355, 15, "Title Include?", "IncludeAlsoT"		
	MakeEDITbx Panel_1, 220, 21, 355, 15, "Artist Include?", "IncludeAlsoA"		
	MakeCHECKbx Panel_1, 590, 5, 100, 30, "+Expand Title+", "ExpandTitleL"
	MakeCHECKbx Panel_1, 695, 5, 20, 30, "", "ExpandTitleR"
	MakeCHECKbx Panel_1, 730, 5, 80, 30, "Any Artist", "AnyArtist"
	MakeCHECKbx Panel_1, 830, 5, 80, 30, "fuzzy match?", "Fuzzy"		
	MakeCHECKbx Panel_1, 930, 0, 110, 20, "allow karaoke", "AllowKaroke"	
	MakeCHECKbx Panel_1, 930, 20, 110, 20, "stay in genre", "StayInGenre"	
	MakeBUTTON Panel_1, 1050,  5, 220, 30, "Next Track", "NextTrack", 10, "blue", "", ""
	MakeBUTTON Panel_1, 1275,  5, 100, 30, "Next Dup Set", "NextDupSet", 10, "blue", "", ""
	MakeBUTTON Panel_1, 1400,  5, 100, 30, "Merge All", "MergeTracks"	, 10, "blue", "all", ""	
	MakeBUTTON Panel_1, 1505,  5, 100, 30, "Merge Selected", "MergeTracks", 10, "blue", "selected", ""	
	MakeBUTTON Panel_1, 1700,  5, 100, 30, "Quit", "Quit", 10, "blue", "", ""
	
	Panel_1.Common.ChildControl("ExpandTitleR").Checked = True
	
	FreshSong("")
End Sub

Sub FreshSong(Btn)
	Set CurrentSong = SDB.Player.CurrentSong 	
	MatchTitle = SqlFriendly( CurrentSong.Title )
	MatchTitle=Trim(Replace(Replace(Replace(Replace(Replace(Replace(MatchTitle,"'",""),",",""),"!",""),"-"," "),"?",""),".",""))
	MatchTitleCore = MatchTitle
	MatchTitleCore = CoreTitle( MatchTitleCore )
	MatchArtist = SqlFriendly( CurrentSong.ArtistName )	
	MatchGenre = LCase(CurrentSong.Genre)
	If MatchGenre = "karaoke" Then Panel_1.Common.ChildControl("AllowKaroke").Checked = True
	
	DuppyForm.Caption = MatchArtist & " - " & MatchTitleCore
	Panel_1.Common.ChildControl("EBXIncludeAlsoT").Text = "Title Include?"
	Panel_1.Common.ChildControl("EBXIncludeAlsoA").Text = "Artist Include?"
	Panel_1.Common.ChildControl("ExpandTitleL").Checked = False
	Panel_1.Common.ChildControl("ExpandTitleR").Checked = True
	Panel_1.Common.ChildControl("Fuzzy").Checked = False
	Panel_1.Common.ChildControl("AllowKaroke").Checked = False
	If ArtistGenreAutocheck = True Then
		Panel_1.Common.ChildControl("StayInGenre").Checked = False
		Panel_1.Common.ChildControl("AnyArtist").Checked = False	
	end if

	FreshSngList("")
End Sub

Sub FreshSngList(Btn)
	Dim SQL, QueryResults, AlsoSearchT, AlsoSearchA, z, MultiAlsoT, MultiAlsoA, AlsoListT
	Dim AlsoListA, LeftWild, RightWild, KaraokeOK, GenreLimit	
	
	Revision = 0 ' this WAS located above ??
	
	Set SongList = Nothing
	Set SongList = SDB.NewSongList
	SongList.Add(CurrentSong)	
	If Not DicOffset.Exists(CStr(CurrentSong.ID)) Then DicOffset.add CStr(CurrentSong.ID), 0
	
	RightWild = "" : LeftWild = ""
	
	If Panel_1.Common.ChildControl("ExpandTitleR").Checked Then RightWild = "%"
	If Panel_1.Common.ChildControl("ExpandTitleL").Checked Then LeftWild = "%"
		
	AlsoSearchT = Panel_1.Common.ChildControl("EBXIncludeAlsoT").Text
	AlsoSearchA = Panel_1.Common.ChildControl("EBXIncludeAlsoA").Text
	
	AlsoListT = "" : AlsoListA = ""
		
	If InStr(LCase(MatchTitle), "a ")   = 1 _
	Or InStr(LCase(MatchTitle), "the ") = 1 _
	Or InStr(LCase(MatchTitle), "an ")  = 1  Then
		Panel_1.Common.ChildControl("ExpandTitleL").Checked = True
		LeftWild = "%"
	end if
	
	SQL="Replace(Replace(Replace(Replace(Replace(Replace(SongTitle,'''',''),',',''),'!',''),'-',' '),'?',''),'.','') LIKE '" _
			& LeftWild & MatchTitleCore & RightWild & "'"
	
	If Panel_1.Common.ChildControl("Fuzzy").Checked Then 
		SQL = "( SongTitle LIKE '" & LeftWild & MatchTitleCore & RightWild & "'"
		SQL = SQL & " OR ( SOUNDEX(SongTitle) = SOUNDEX('"& MatchTitleCore &"') ) )"
	end if

	If AlsoSearchT <> "Title Include?" And AlsoSearchT <> "" Then 
		if InStr( AlsoSearchT, ";" ) Then
			MultiAlsoT = Split( AlsoSearchT, ";" )		
			for z = 0 To UBound(MultiAlsoT ) 
				AlsoListT = AlsoListT & " OR SongTitle LIKE '%" & SqlFriendly( MultiAlsoT(z) ) & "%'"	'added %
			next
			SQL = "(" & SQL & AlsoListT & ")"
		Else
			SQL = "(" & SQL & " OR SongTitle LIKE '%" & SqlFriendly(AlsoSearchT) & "%')"   ' added %
		end if
	end if
	
	If Not Panel_1.Common.ChildControl("AnyArtist").Checked Then 
		SQL = SQL & " AND (Artist LIKE '%" & MatchArtist  & "%' OR AlbumArtist LIKE '%" & MatchArtist  & "%'"
		
		If AlsoSearchA <> "Artist Include?" And AlsoSearchA <> "" Then 
			if InStr( AlsoSearchA, ";" ) Then
				MultiAlsoA = Split( AlsoSearchA, ";" )		
				for z = 0 To UBound(MultiAlsoA ) 
					AlsoListA = AlsoListA & " OR Artist LIKE '%" & SqlFriendly( MultiAlsoA(z) ) & _
											"%' OR AlbumArtist LIKE '%" & SqlFriendly( MultiAlsoA(z) ) & "%'"
				next
				SQL = SQL & AlsoListA 
			Else
				SQL = SQL & " OR Artist LIKE '%" & SqlFriendly(AlsoSearchA) & "'"
			end if
		end if	
		
		SQL = SQL & " )"
		
	End IF	
	
	KaraokeOK = Panel_1.Common.ChildControl("AllowKaroke").Checked
	GenreLimit = Panel_1.Common.ChildControl("StayInGenre").Checked
		
	If KaraokeOK = True And GenreLimit = True Then
		If MatchGenre = "karaoke" Then
			SQL = SQL & "AND (GENRE LIKE 'KARAOKE')"	
		Else
			SQL = SQL & "AND (GENRE LIKE '" & MatchGenre & "' OR GENRE LIKE 'KARAOKE')"	
		end if	
	ElseIf KaraokeOK = False And GenreLimit = True Then
		SQL = SQL & "AND (GENRE LIKE '" & MatchGenre & "')"			
	ElseIf KaraokeOK = False And GenreLimit = False Then
		SQL = SQL & " AND (GENRE NOT LIKE '%KARAOKE%')"			
	end if
	
	Set QueryResults = SDB.Database.QuerySongs( SQL )	
	
	QueryEmpty = True
	While Not QueryResults.EOF
			If QueryResults.Item.Path <> CurrentSong.Path Then 
				QueryEmpty = False
				SongList.Add(QueryResults.Item) 
				If Not DicOffset.Exists(CStr(QueryResults.Item.ID)) Then DicOffset.add CStr(QueryResults.Item.ID), 0
			end if
			QueryResults.Next
	Wend		
	
	If AutoMode = True And QueryEmpty = True Then
		NextTrack("")
	Else
		AutoMode = False 
		If Not SDB.Player.isPlaying Then SDB.Player.Play 
		MakeTheEntries
	end if
end sub
		
Sub MakeTheEntries
	Dim Panel_x, Song, i, z, SongRating, thebitrate, bitratecolor, AlbumArt, Image, TmpImage, TmpFile, WebBrowser
	Dim rownumber, condition, conditionColor, Panel_html, channels, channelcolor, qualitycolor, imagesizecolor, FileType
	
	Set Panel_2 = Nothing
	Set Panel_2 = UI.NewGroupBox(DuppyForm) : Panel_2.Common.SetRect 5, 50, 1825, 1050 
	
	rownumber = 0 			
	For i = 0 To SongList.Count -1
			Set Song = SongList.Item(i)				
			
			Set Panel_x = UI.NewGroupBox(Panel_2) : Panel_x.Common.SetRect 10, (rownumber * 100) + 10, 1805, 95  		
			
			If Song.Channels = 2 Then
				channels = "S" : channelcolor = "pink" 
			Else
				channels = "M" : channelcolor = "brown"
			End if
			
			qualitycolor = "mint"
			If InStr(Song.Quality, "VPI") Then qualitycolor = "yellow"
			If InStr(Song.Quality, "CD") Then qualitycolor = "green"
			
			FileType = LCase( Mid( Song.Path, InStrRev( Song.Path, ".") + 1 ) )
			
			MakeCHECKbx Panel_x, 5, 0, 35, 35, "", ControlNameFromPath( Song.Path )					
			MakeBUTTON Panel_x, 5, 37, 30, 20, "remove", "MinusSong", 5, "fushia", Song.ID, ""
			MakeBUTTON Panel_x, 5, 67, 30, 20, "delete", "MinusSong", 5, "fushia", Song.ID, ""
			
			MakeEDITbx Panel_x, 50,  5, 300, 25, Song.Title, "TTT" & Revision & Song.ID
			MakeEDITbx Panel_x, 50, 35, 300, 25, Song.ArtistName, "NNN" & Revision & Song.ID
			MakeEDITbx Panel_x, 50, 65, 300, 25, Song.AlbumArtistName, "EEE" & Revision & Song.ID			
			MakeBUTTON Panel_x, 355,  7, 30, 20, "update", "Update", 5, "fushia", Song.ID, ""
			if FileType = "flac" Then
				if InStr(Song.Custom3, "(>m)") = 0 And Song.Channels > 1 Then
					MakeBUTTON Panel_x, 390,  7, 30, 20, "MONO", "MonoMe", 5, "fushia", Song.ID, ""
				end if
			end if
			
			MakeEDITbx Panel_x, 425,  5, 170, 25, Song.Genre, "GGG" & Revision & Song.ID
			MakeEDITbx Panel_x, 355, 35, 240, 25, Song.Conductor, "CCC" & Revision & Song.ID
			MakeEDITbx Panel_x, 355, 65, 240, 25, Song.AlbumName, "AAA" & Revision & Song.ID
			
			MakeLABELS Panel_x, 610, 25, 120, 40, Song.SongLengthString, 25, "fushia", 2, "bold" 
			MakeLABELS Panel_x, 755, 25,  55, 40, channels, 25, channelcolor, 2, "bold"
			MakeLABELS Panel_x, 810, 33, 140, 40, Song.Quality, 16, qualitycolor, 2, "bold"
			
			thebitrate = Round(Song.Bitrate / 1000)
			If thebitrate < 192 Then bitratecolor = "red"
			If thebitrate > 191 Then bitratecolor = "yellow"	
			If FileType = "flac" Then bitratecolor = "green"			
			MakeLABELS Panel_x, 960, 25, 130, 40, thebitrate, 25, bitratecolor, 2, "bold"    
			
			condition = Song.Custom3 
			conditionColor = "ochre" : If InStr(condition,"POOR") Or InStr(condition, "GLITCH") Then conditionColor = "red"			
			MakeLABELS Panel_x, 1100, 15, 217, 40, condition, 12, conditionColor, 2, "bold"			
			MakeLABELS Panel_x, 1100, 55, 217, 40, Song.Comment, 12, conditionColor, 2, "bold"
			
			MakeBUTTON Panel_x, 1318,  3, 17, 30, "-", "OffsetMinus", 10, "fushia", Song.ID, ""
			MakeLABELS Panel_x, 1318, 40, 17, 20, DicOffset.Item(CStr(Song.ID)), 8, "pink", 2, "bold" 
			MakeBUTTON Panel_x, 1318, 63, 17, 30, "+", "OffsetPlus", 10, "fushia", Song.ID, ""
			
			MakeBUTTON Panel_x, 1340,  3, 50, 15, "PLAY", "PLAY1", 7, "fushia", Song.ID, ""
			MakeBUTTON Panel_x, 1340, 21, 50, 15, "PLAY2", "PLAY2", 7, "fushia", Song.ID, ""
			MakeBUTTON Panel_x, 1340, 39, 50, 15, "PLAY3", "PLAY3", 7, "fushia", Song.ID, ""
			MakeBUTTON Panel_x, 1340, 57, 50, 15, "PLAY½", "PLAYHALF", 7, "fushia", Song.ID, ""
			MakeBUTTON Panel_x, 1340, 75, 50, 15, "END", "PLAY4", 7, "fushia", Song.ID, ""
			
			MakeBUTTON Panel_x, 1400, 5, 200, 22, Song.Grouping, "GroupingWork", 10, "fushia", Song.ID, ""			
			SongRating = ""
			If Song.Rating > 0 Then : for z = 1 To Song.Rating / 20 : SongRating = SongRating & ChrW(&H25c6) : next : End if			
			MakeLABELS Panel_x, 1400, 33, 200, 15, SongRating, 8, "gold", 2, "bold"  
			MakeLABELS Panel_x, 1400, 53, 200, 20, Song.Mood, 10, "clay", 2, "bold"
			MakeLABELS Panel_x, 1400, 75, 200, 20, Song.Custom2, 9, "clay", 2, "bold"
							
			Set Panel_html = UI.NewGroupBox( Panel_x ) 
			Panel_html.Common.SetRect 1610, 0, 95, 95 				
			
			Set AlbumArt = Song.AlbumArt
			If AlbumArt.count > 0 Then 
					Set Image = AlbumArt.Item(0).Image
					TmpImage = TmpPath & rownumber & ".jpg"
	
					Set TmpFile = SDB.Tools.FileSystem.CreateTextFile( TmpImage, True)
					Dim ImageNew : Set ImageNew = Image.convertformat( 128, 128, "image/jpeg", 100, -1) 
					TmpFile.writedata ImageNew.imagedata, ImageNew.imagedatalen
					TmpFile.close : Set ImageNew = Nothing
					
					Set WebBrowser = UI.NewActiveX( Panel_html, "Shell.Explorer" )
					WebBrowser.Common.ControlName = "WebBrowser"
					WebBrowser.Interf.document.body.innerHTML = _
					"<img style=""border:none;margin:-16px,-11px;padding:0px;overflow:hidden;height:128px;width:128px;"" src=""" & TmpImage & """>"  				
					SDB.Objects("WebBrowser" & rownumber) = WebBrowser
					
					imagesizecolor = "green"
					if Image.Width < 400 Then imagesizecolor = "clay"					
					if Image.Width > 800 Then imagesizecolor = "pink"
					
				MakeBUTTON Panel_x, 1720, 5, 75, 30, "FULL", "ShowArtFull", 12, "fushia", Song.ID, ""  
				MakeLABELS Panel_x, 1720, 40, 70, 20, Image.Width & "x" & Image.Height, 10, imagesizecolor, 0, "bold"
				MakeBUTTON Panel_x, 1720, 60, 75, 30, ">selected", "ArtToSelected", 10, "fushia", Song.ID, ""  
			End If
			rownumber = rownumber + 1
	Next		
End Sub

Sub NextDupSet(Btn)
	If SDB.Player.isPlaying Or SDB.Player.isPaused Then SDB.Player.Stop	
	AutoMode = True
	NextTrack("")	
end sub

Sub NextTrack(Btn)
	Dim x
	If SDB.Player.isPlaying Or SDB.Player.isPaused Then SDB.Player.Stop	
	
	If SDB.PlaylistByTitle("Duppy").Id = 0 Then	' expand this error control !
		MsgBox "~NEXT~ only works with *Duppy* playlist" : exit sub
	end if
	
'	If SDB.PlaylistByTitle("Duppy").Tracks.Count > 0 Then 
'		SDB.PlaylistByTitle("Duppy").RemoveTrackNoConfirmation SDB.PlaylistByTitle("Duppy").Tracks.Item(0)
'	end if
'	SDB.MainTracksWindow.Refresh	
	If ClearNowPlaying = True Then SDB.Player.PlaylistClear	
		
	If SDB.PlaylistByTitle("Duppy").Tracks.Count > 0 Then 				
		For x = 0 To SongList.Count -1
			If SDB.PlaylistByTitle("Duppy").Tracks.Count > 0 Then 'new 9/7
				if  SDB.PlaylistByTitle("Duppy").Tracks.Item(0).Path = SongList.Item(x).Path Then
					SDB.PlaylistByTitle("Duppy").RemoveTrackNoConfirmation SDB.PlaylistByTitle("Duppy").Tracks.Item(0)
					SDB.MainTracksWindow.Refresh	
				end if
			end if
		next			
			
		If SDB.PlaylistByTitle("Duppy").Tracks.Count > 0 Then 				
			SDB.Player.PlaylistAddTrack SDB.PlaylistByTitle("Duppy").Tracks.Item(0)
			If Not SDB.Player.isPlaying Then SDB.Player.Play
			While SDB.Player.IsStartingPlayback
				SDB.ProcessMessages
			Wend
			If AutoMode = True Then SDB.Player.Stop
			
			FreshSong("")
			
		Else
			SDB.MessageBox "no more playlist items", mtError, Array(mbOk)
		End If	
					
	Else
		SDB.MessageBox "no more playlist items", mtError, Array(mbOk)
	End If
End Sub

Sub Update(Btn)
	Dim track, sngID, Arr, i
	sngID = Btn.Common.Hint	
	Set track = SDB.Database.QuerySongs("Songs.ID=" & sngID ).item	

	if DuppyForm.Common.ChildControl("EBXTTT" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.Title = DuppyForm.Common.ChildControl("EBXTTT" & Revision & sngID).Text 
	if DuppyForm.Common.ChildControl("EBXNNN" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.ArtistName = DuppyForm.Common.ChildControl("EBXNNN" & Revision & sngID).Text
	if DuppyForm.Common.ChildControl("EBXEEE" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.AlbumArtistName = DuppyForm.Common.ChildControl("EBXEEE" & Revision & sngID).Text
	if DuppyForm.Common.ChildControl("EBXGGG" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.Genre = DuppyForm.Common.ChildControl("EBXGGG" & Revision & sngID).Text
	if DuppyForm.Common.ChildControl("EBXCCC" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.Conductor = DuppyForm.Common.ChildControl("EBXCCC" & Revision & sngID).Text
	if DuppyForm.Common.ChildControl("EBXAAA" & Revision & sngID).Common.FontColor = GetVbColor( "red" ) Then _
	   track.AlbumName = DuppyForm.Common.ChildControl("EBXAAA" & Revision & sngID).Text
	
	track.WriteTags : track.UpdateDB
	
	Revision = Revision + 1
	
	MakeTheEntries
End sub

sub GroupingWork(Btn) 
	Dim playlists, playlist, TheSelectedSongs, SourceTrack, destinationPL, DicGroupingSmall
	
	Set SourceTrack = SDB.Database.QuerySongs("Songs.ID=" & Btn.Common.Hint).Item
	If SourceTrack.Grouping <> "" Then
		playlists = Split( SourceTrack.Grouping, ";" )
		
		Set TheSelectedSongs = GetSelectedTracks
		For x = 0 To (TheSelectedSongs.Count - 1) 
			for each playlist In playlists
				playlist = Trim(playlist)
				if Not InStr(TheSelectedSongs.Item(x).Grouping, playlist) Then
				
					if TheSelectedSongs.Item(x).Grouping = "" Then
						TheSelectedSongs.Item(x).Grouping = playlist
					Else
						TheSelectedSongs.Item(x).Grouping = TheSelectedSongs.Item(x).Grouping & "; " & playlist 
					end if 
					
					If SDB.PlaylistByTitle(playlist).Id = 0 Then	SDB.PlaylistByTitle("").CreateChildPlaylist(playlist) 
					SDB.PlaylistByTitle(playlist).AddTrack( TheSelectedSongs.Item(x) ) '' way to test if track already there?
					
					TheSelectedSongs.Item(x).UpdateDB
				end if
			next
		next
	end if
	
	TheSelectedSongs.UpdateAll
	
	MakeTheEntries
end sub

Sub ArtToSelected(Btn)
	Dim GoodArt, ArtCopy, ArtFlavor, ArtData, ArtLength, GetArt, TheSelectedSongs, i, SongArt
	
	Set GoodArt = SDB.Database.QuerySongs("Songs.ID=" & Btn.Common.Hint ).Item.AlbumArt.Item(0).Image  
	ArtData = GoodArt.ImageData
	ArtLength = GoodArt.ImageDataLen	
	If GoodArt.ImageFormat = "image/jpeg" Then ArtFlavor = "jpg"
	If GoodArt.ImageFormat = "image/png" Then ArtFlavor = "png"
	If GoodArt.ImageFormat = "image/x-bmp" Then ArtFlavor = "bmp"
	If GoodArt.ImageFormat = "image/gif" Then ArtFlavor = "gif"
	ArtCopy = TmpPath & "TmpCopiedArt." & ArtFlavor
	
	Set GetArt = SDB.Tools.FileSystem.CreateTextFile( ArtCopy, True ) 
	GetArt.WriteData ArtData, ArtLength 
	GetArt.close
	
	Set TheSelectedSongs = GetSelectedTracks
	For i = 0 To (TheSelectedSongs.Count - 1) 
		Set SongArt = TheSelectedSongs.Item(i).AlbumArt 

		Do While SongArt.Count > 0 
			SongArt.Delete(0)
			SongArt.UpdateDB 
		loop
		
		Set NewArt = SongArt.AddNew
		NewArt.PicturePath = ArtCopy
		NewArt.Description = "merged"
		NewArt.ItemType = 3
		NewArt.ItemStorage = 0	
		
		SongArt.UpdateDB	 
	Next
	
	TheSelectedSongs.UpdateAll 

	Set GetArt = Nothing : Set GoodArt = Nothing : Set TheSelectedSongs = Nothing : Set SongArt = Nothing	
	
	MakeTheEntries
end sub

Sub MergeTracks(Btn)
	if ImReadyToAcceptResponsibilityForTagCode = False Then
		MsgBox "For Safety, MERGE is disabled by one code line near the top of the script; Change it when you're sure tags are manipulated to YOUR needs."
		Exit Sub
	end if
	
	Dim MergeSongList
	
	If Btn.Common.Hint = "selected" Then Set MergeSongList = GetSelectedTracks
	If Btn.Common.Hint = "all" Then Set MergeSongList = SongList
	
	Dim MergeSong, counter2, i, z, y, Itm, tagvalue, tmpGet
	Dim LargeRating, GoodDate, displaytype, AllFeelings, AllGetTag, newtag, member
	Dim DicMood, DicSubGenre, DicTempo, DicConductor, DicTheDate, DicRated, DicPicLength, DicGetTag, DicComments	
		
	Set DicMood = CreateObject("Scripting.Dictionary") : DicMood.CompareMode = vbTextCompare
	Set DicFeelings = CreateObject("Scripting.Dictionary") : DicFeelings.CompareMode = vbTextCompare
	Set DicSubGenre = CreateObject("Scripting.Dictionary") : DicSubGenre.CompareMode = vbTextCompare
	Set DicGetTag = CreateObject("Scripting.Dictionary") : DicGetTag.CompareMode = vbTextCompare
	Set DicTempo = CreateObject("Scripting.Dictionary") : DicTempo.CompareMode = vbTextCompare
	Set DicConductor = CreateObject("Scripting.Dictionary") : DicConductor.CompareMode = vbTextCompare
	Set DicTheDate = CreateObject("Scripting.Dictionary") : DicTheDate.CompareMode = vbTextCompare
	Set DicRated = CreateObject("Scripting.Dictionary") : DicRated.CompareMode = vbTextCompare
	Set DicPicLength = CreateObject("Scripting.Dictionary") : DicPicLength.CompareMode = vbTextCompare	
	Set DicComments = CreateObject("Scripting.Dictionary") : DicComments.CompareMode = vbTextCompare	
	Set DicGrouping = CreateObject("Scripting.Dictionary") : DicGrouping.CompareMode = vbTextCompare	

	displaytype = ""   

	SongCount = MergeSongList.Count - 1
	If SongCount < 1 Then : MsgBox "select something genius" : Exit sub : Quit : end if	
	
	'************************** get tags from all  ***************
	For i = 0 To SongCount  
		Set MergeSong = MergeSongList.Item(i)				
		If Not DicMood.Exists(MergeSong.Mood) And MergeSong.Mood <> "" Then DicMood.Add MergeSong.Mood, MergeSong.Mood
		If MergeSong.Custom2 <> ""  Then SplitMulti DicFeelings, MergeSong.Custom2 
		tmpGet = Replace(MergeSong.Custom5,  "UPGRADEme", "" )
		If MergeSong.Custom5 <> ""  Then SplitMulti DicGetTag,  tmpGet
		If Not DicSubGenre.Exists(MergeSong.Custom4) And MergeSong.Custom4 <> ""  Then DicSubGenre.Add MergeSong.Custom4, MergeSong.Custom4
		If Not DicTempo.Exists(MergeSong.Tempo) And MergeSong.Tempo <> ""  Then DicTempo.Add MergeSong.Tempo, MergeSong.Tempo
		If Not DicConductor.Exists(MergeSong.Conductor) And MergeSong.Conductor <> ""  Then DicConductor.Add MergeSong.Conductor, MergeSong.Conductor
		If Not DicTheDate.Exists(MergeSong.Year) And MergeSong.Year <> ""  Then DicTheDate.Add MergeSong.Year, MergeSong.Year
		If Not DicRated.Exists(MergeSong.Rating) And MergeSong.Rating <> ""  Then DicRated.Add MergeSong.Rating, MergeSong.Rating
		If Not DicComments.Exists(MergeSong.Comment) And MergeSong.Comment <> ""  Then DicComments.Add MergeSong.Comment, MergeSong.Comment
		If MergeSong.OriginalTitle <> "" Then displaytype = MergeSong.OriginalTitle 'will be last existing tag, but good enough~		
	Next

'''''''''moods & feelings
	If DicMood.Count = 0 Then 
		OneMood = ""
	ElseIf DicMood.Count = 1 Then 
		OneMood = DicMood.Keys()(0)
	ElseIf DicMood.Count > 0 Then 
		For i = 0 To DicMood.Count - 1
			newtag = DicMood.Keys()(i)
			if Not DicFeelings.Exists(newtag) Then DicFeelings.Add newtag, newtag
		Next		
		MakeMergeForm "Mood", DicMood	
	end if
		
	if DicFeelings.Exists(OneMood) Then DicFeelings.Remove(OneMood)
	
	AllFeelings = ""
	If DicFeelings.Count > 0 Then
		For each member In DicFeelings ' "remove" still leaves a blank member!
			If member <> "" Then AllFeelings = AllFeelings & "; " & member
		next
		AllFeelings = Mid(AllFeelings, 2)
	end if
	
''''''''''GET	
	AllGetTag = ""
	If DicGetTag.Count > 0 Then
		For each member In DicGetTag
			If member <> "" Then AllGetTag = AllGetTag & "; " & member
		next
		AllGetTag = Mid(AllGetTag, 2)
	end if
	
'''''''ratings 
	counter2 = 0 : 	LargeRating = 0 : 	OneRating = -1
	For i = 0 To DicRated.Count - 1
		tagvalue = DicRated.Keys()(i)
		If tagvalue > 30 Then         'ignore less than 2 stars   
			LargeRating = LargeRating + tagvalue
			counter2 = counter2 + 1
		End If
	Next
	If LargeRating > 0 Then OneRating = ((LargeRating / counter2) \ 20) * 20 	'no half stars!
	
	''''''''''date
	For i = 0 To DicTheDate.Count - 1
		tagvalue = DicTheDate.Keys()(i)
		If GoodDate < 1 Then GoodDate = tagvalue		
		If tagvalue > 1 And GoodDate > tagvalue Then GoodDate = tagvalue
	Next
	
'''''''subgenre	
	If DicSubGenre.Count = 0 Then
		OneSubGenre = ""
	ElseIf DicSubGenre.Count = 1 Then
		OneSubGenre = DicSubGenre.Keys()(0)
	ElseIf DicSubGenre.Count > 1 Then
		MakeMergeForm "SubGenre", DicSubGenre 
	End if	

''''''''''tempo	
	If DicTempo.Count = 0 Then
		OneTempo = ""
	ElseIf DicTempo.Count = 1 Then
		OneTempo = DicTempo.Keys()(0)
	ElseIf DicTempo.Count > 1 Then
		MakeMergeForm "Tempo", DicTempo 
	End if	

''''''''''conductor	
	If DicConductor.Count = 0 Then
		OneConductor = ""
	ElseIf DicConductor.Count = 1 Then
		OneConductor = DicConductor.Keys()(0)
	ElseIf DicConductor.Count > 1 Then
		MakeMergeForm "Conductor", DicConductor 
	End if		

'''''''''''comments
	OneComment = ""
	If Not DicComments.Exists("CLEAR ALL") Then DicComments.Add "CLEAR ALL", "CLEAR ALL"
	If DicComments.Count > 1 Then
		MakeMergeForm "Comment", DicComments 
	End if
						
	'************************* write tags to all  *******************
	For i = 0 To SongCount
		Set Itm = MergeSongList.Item(i)
		
		Itm.Year = GoodDate   
		Itm.Custom2 = AllFeelings
		if OneMood <> "" Then Itm.Mood = OneMood
		if OneSubGenre <> "" Then Itm.Custom4 = OneSubGenre  
		if OneTempo <> "" Then Itm.Tempo = OneTempo
		if OneConductor <> "" Then Itm.Conductor = OneConductor
		if OneComment <> "" Then 
			if OneComment = "CLEAR ALL" Then 
				Itm.Comment = ""
			Else
				Itm.Comment = OneComment
			end if
		end if
		
		If displaytype <> "" Then itm.OriginalTitle = displaytype
		If Itm.Rating <> 20 And Itm.Rating <> 0 Then Itm.Rating = OneRating
		
		If InStr(Itm.Custom5, "UPGRADEme") = 0 Then  
			Itm.Custom5 = AllGetTag
		Else
			Itm.Custom5 = "UPGRADEme; " & AllGetTag
			If Itm.Custom5 = "UPGRADEme; " Then Itm.Custom5 = "UPGRADEme"
		End If
		
	Next															
	
	MergeSongList.UpdateAll	
	
	Set MergeSong = Nothing    :  Set DicGetTag = Nothing   : Set DicMood = Nothing
	Set DicComments = Nothing  :  Set DicRated = Nothing    : Set DicConductor = Nothing
	Set DicSubGenre =Nothing   : 	Set DicTheDate = Nothing  : Set DicTempo = Nothing
	Set MergeSongList = Nothing : Set DicFeelings = Nothing
	
	MakeTheEntries
End Sub

Sub MakeMergeForm( WhichTag, WhichDictionary )
		Dim x, z, SelectionFormLabel
		
		Execute( "One" & WhichTag & " = """"" ) ''new 9/7
		
		Set SelectionForm = UI.NewForm
		Set SDB.Objects("MergeFormObject") = SelectionForm
		SelectionForm.Caption = "Too Many Tags"
		SelectionForm.Common.SetRect 120, 80, 1000, 777
		SelectionForm.BorderStyle = 2 ' Resizable 
		SelectionForm.FormPosition = 4 ' Screen Center 
		SelectionForm.StayOnTop = True
		SelectionForm.SavePositionName = "SelectionFormPosition"
																													
		Set SelectionFormLabel = SDB.UI.NewLabel(SelectionForm)
		SelectionFormLabel.Caption = "Pick the " & 	UCase(WhichTag)
		SelectionFormLabel.Common.SetRect 412, 4, 160, 17
		
		MakeBUTTON SelectionForm, 444, 484, 155, 25, "skip this tag", "none", "", "", "cancel", "cancel"

		For x = 0 To WhichDictionary.Count - 1  
			MakeBUTTON SelectionForm, (x * 200) + 8, 30, 188, 88, WhichDictionary.Keys()(x), "ChooseOne", "", "", WhichTag, 1 			
		next
		
		If WhichTag = "Mood" Then 
			for z = 0 To DicFeelings.Count - 1 
				MakeLABELS SelectionForm, 22, 144 + (z * 56), 944, 44, DicFeelings.Keys()(z), "", "", 1, ""  
			next
		End If
		
		SelectionForm.ShowModal 
End Sub

Sub ChooseOne(Btn)
	if Btn.Common.Hint = "Mood" Then OneMood = Btn.Caption 
	if Btn.Common.Hint = "SubGenre" Then OneSubGenre = Btn.Caption 
	if Btn.Common.Hint = "Tempo" Then OneTempo = Btn.Caption 
	if Btn.Common.Hint = "Conductor" Then OneConductor = Btn.Caption 	
	if Btn.Common.Hint = "Comment" Then OneComment = Btn.Caption 	
	
	Set SelectionForm = Nothing : Set SDB.Objects("MergeFormObject") = Nothing	
End Sub

Sub SplitMulti( dictionary, multitag )
	multitag = Replace( multitag, "  ", " " )
	multitag = Replace( multitag, "; ", ";" )
	multitag = Replace( multitag, " ;", ";" )
	multitag = Replace( multitag, ";;", ";" )
	
	If InStr( multitag, ";" ) = 0 Then
		If Not dictionary.Exists(multitag) Then dictionary.Add multitag, multitag
	Else		
		Dim SplitTag, i, tmptag
		SplitTag = Split( multitag, ";" )
		for i = 0 To UBound(SplitTag)
			tmptag = Trim( SplitTag(i) )
			If Not dictionary.Exists(tmptag) Then dictionary.Add tmptag, tmptag
		next
		
		Set SplitTag = Nothing
	end if
	
end sub

Function GetSelectedTracks()
	Dim CheckedSongs, x, uniquename
	Set CheckedSongs = SDB.NewSongList
	For x = 0 To SongList.Count - 1
		uniquename = "CBX" & ControlNameFromPath( SongList.Item(x).Path )
		If SDB.Objects(uniquename).Checked Then CheckedSongs.Add( Songlist.Item(x) )  
	next
	
	Set GetSelectedTracks = CheckedSongs
End function

Sub MinusSong(Btn)
	Dim BadSong, DeleteList, x

	For x = (SongList.Count - 1) To 0 Step -1
		If CStr(SongList.Item(x).ID) = Btn.Common.Hint Then 
			DicOffset.Remove(CStr(SongList.Item(x).ID))
			SongList.Delete(x)
		end if
	next
	
	If Btn.Caption = "delete" Then
		Set BadSong = SDB.Database.QuerySongs("Songs.ID=" & Btn.Common.Hint).Item
		Set DeleteList = SDB.NewSongList
		
		DeleteList.Add BadSong			
		SDB.Tools.DeleteTracks DeleteList,True,1 'true = confirm 			
		DeleteList.UpdateAll ''new 9/7
		SDB.MainTracksWindow.Refresh
				
		Set BadSong = Nothing : Set DeleteList = Nothing
	end if
	
	MakeTheEntries	
End Sub

Sub ShowArtFull(Btn)		
	Dim ArtForm, TheSong, FullArt, WB, TmpFile, iter, TmpImage
	
	Set TheSong = SDB.Database.QuerySongs("Songs.ID=" & Btn.Common.Hint ).Item
	
	Set FullArt = TheSong.AlbumArt.Item(0).Image  
	TmpImage = TmpPath & "TmpAlbumArtFull.jpg"
	Set ImageNew = FullArt.convertformat( FullArt.Width, FullArt.Height, "image/jpeg", 100, 0)
	Set TmpFile = SDB.Tools.FileSystem.CreateTextFile( TmpImage, True)
	TmpFile.writedata ImageNew.imagedata, ImageNew.imagedatalen
	TmpFile.close		

	Set ArtForm = UI.NewForm
	ArtForm.Common.SetRect 10, 10, CInt(FullArt.Width * .78), CInt(FullArt.Height * .8)
	ArtForm.FormPosition = 0  
	ArtForm.BorderStyle = 2
	'ArtForm.SavePositionName = "ArtForm"
	ArtForm.Caption = Right(Btn.Common.Hint, InStr(Btn.Common.Hint, "/")) 
	ArtForm.Common.Visible = True
	SDB.Objects("ArtForm" ) = ArtForm
		
	Set Webby = UI.NewActiveX( ArtForm, "Shell.Explorer" )
   Webby.Common.ClientWidth = ArtForm.Common.ClientWidth
   Webby.Common.ClientHeight = ArtForm.Common.ClientHeight
	Webby.Common.ControlName = "Webby"	
	
	Webby.Interf.document.body.innerHTML = "<img style=""border:none;margin:-16px, -11px;padding:0px;"" src=""" & TmpImage & """>"
	
	SDB.Objects("Webby" ) = Webby
end sub

Function CoreTitle(uncleanTitle)
	If InStr(uncleanTitle, "(" ) > 1 Then
		Do While InStr(uncleanTitle,"(") > 1
			uncleanTitle = Left(uncleanTitle,InStrRev(uncleanTitle,"(")-1)
		loop
	ElseIf InStr(uncleanTitle, "(" ) = 1 Then
		uncleanTitle = Mid(uncleanTitle, InStr(uncleanTitle, ")") + 1 )
	end if
	Do While InStr(uncleanTitle,"[") > 0
		uncleanTitle = Left(uncleanTitle,InStrRev(uncleanTitle,"[")-1)
	loop
	Do While InStr(uncleanTitle,"{") > 0
		uncleanTitle = Left(uncleanTitle,InStrRev(uncleanTitle,"{")-1)
	loop
	If Left(LCase(uncleanTitle),2) = "a " Then
			uncleanTitle = Mid(uncleanTitle,3)
	ElseIf Left(LCase(uncleanTitle),3) = "an " Then
			uncleanTitle = Mid(uncleanTitle,4)
	ElseIf Left(LCase(uncleanTitle),4) = "the " Then
			uncleanTitle = Mid(uncleanTitle,5)
	End If
	
	CoreTitle = Trim(uncleanTitle)
End Function

Function SqlFriendly( str )
	SqlFriendly = Trim(Replace(str,"'","''"))
end function

Function ControlNameFromPath( original )	
	ControlNameFromPath = Trim(Replace( original, " ", "µ" )) ' space
	ControlNameFromPath = Replace( ControlNameFromPath, "-", "Å" ) ' hyphen
	ControlNameFromPath = Replace( ControlNameFromPath, "–", "Å" ) ' hyphen 2	
	ControlNameFromPath = Replace( ControlNameFromPath, "'", "Â" ) ' apostrophe
	ControlNameFromPath = Replace( ControlNameFromPath, "´", "Â" ) ' apostrophe 2
	ControlNameFromPath = Replace( ControlNameFromPath, "`", "Â" ) ' apostrophe 3
	ControlNameFromPath = Replace( ControlNameFromPath, "’", "Â" ) ' single quote
	ControlNameFromPath = Replace( ControlNameFromPath, "~", "þ" ) ' tilde
	ControlNameFromPath = Replace( ControlNameFromPath, ",", "ã" ) ' comma
	ControlNameFromPath = Replace( ControlNameFromPath, ".", "ç" ) ' period
	ControlNameFromPath = Replace( ControlNameFromPath, ")", "ë" ) ' )
	ControlNameFromPath = Replace( ControlNameFromPath, "(", "ê" ) ' (
	ControlNameFromPath = Replace( ControlNameFromPath, "[", "Ï" ) ' [
	ControlNameFromPath = Replace( ControlNameFromPath, "]", "ñ" ) ' ]
	ControlNameFromPath = Replace( ControlNameFromPath, "\", "è" ) ' \
	ControlNameFromPath = Replace( ControlNameFromPath, "/", "ð" ) ' /
	ControlNameFromPath = Replace( ControlNameFromPath, ":", "î" ) ' :
	ControlNameFromPath = Replace( ControlNameFromPath, ";", "ø" ) ' ;
	ControlNameFromPath = Replace( ControlNameFromPath, "{", "õ" ) ' {
	ControlNameFromPath = Replace( ControlNameFromPath, "}", "ô" ) ' }
	ControlNameFromPath = Replace( ControlNameFromPath, "+", "Ö" ) ' +
	ControlNameFromPath = Replace( ControlNameFromPath, "&", "Š" ) ' &
	ControlNameFromPath = Replace( ControlNameFromPath, "^", "ü" ) ' ^
	ControlNameFromPath = Replace( ControlNameFromPath, "%", "û" ) ' %
	ControlNameFromPath = Replace( ControlNameFromPath, "$", "Ú" ) ' $
	ControlNameFromPath = Replace( ControlNameFromPath, "#", "Ÿ" ) ' #
	ControlNameFromPath = Replace( ControlNameFromPath, "@", "Ž" ) ' @
	ControlNameFromPath = Replace( ControlNameFromPath, "!", "Ð" ) ' !
	ControlNameFromPath = Replace( ControlNameFromPath, "Ã", "ã" ) ' !
	
end function

Sub MakeEDITbx( panel, x, y, width, height, text, control )
	Dim Edit : Set Edit = UI.NewEdit( panel ) '
	Edit.Common.SetRect x, y, width, height	
	Edit.Text =  text
	if InStr(control, "IncludeAlso") Then
		Edit.Common.FontSize = 7
		Edit.Common.FontColor = GetVbColor( "white" )
	end if
	Edit.Common.ControlName = "EBX" & control	
	Script.RegisterEvent Edit,"OnChange", "ColorChange"  
End Sub

Sub MakeCHECKbx( panel, x, y, width, height, caption, control )
		Dim ChB, Unique
		Set ChB = UI.NewCheckBox( panel ) 
		ChB.Common.SetRect x, y, width, height
		ChB.Caption = caption
		ChB.Common.ControlName = control
		Unique = "CBX" & control
		SDB.Objects( Unique ) = ChB 
		If control = StayInGenre Then Script.RegisterEvent ChB, "OnChange", KaraokeChecked 'new 4
End Sub

Sub MakeLABELS( panel, x, y, width, height, caption, size, color, alignment, special  )
	Dim Label : Set Label = UI.NewLabel( panel )
	Label.Autosize = False 
	Label.Common.SetRect  x, y, width, height
	Label.Common.MinWidth = width : Label.Common.MinHeight = height
	Label.Caption = caption
	if size <> "" Then Label.Common.FontSize = size
	if color <> "" Then Label.Common.FontColor = GetVbColor( color )
	Label.Alignment = alignment
	If special = "bold" Then Label.Common.FontBold = True	
End Sub

Sub MakeBUTTON( panel, x, y, width, height, caption, onclick, size, color, hint, modal )
	Dim Btn : Set Btn = UI.NewButton(panel)
	Btn.Common.SetRect x, y, width, height
	Btn.Common.ControlName = onclick
	Btn.Caption = caption
	if size <> "" Then Btn.Common.FontSize = size
	if color <> "" Then Btn.Common.FontColor = GetVbColor( color )	
	if onclick <> "none" Then Script.RegisterEvent Btn.Common, "OnClick", onclick
	Btn.Common.Hint = hint
	if modal <> "" Then
		if modal = "cancel" Then		
			Btn.ModalResult = 2
			Btn.Cancel = True  
		ElseIf modal = 1 Then
			Btn.ModalResult = 1 
		end if
	end if
End Sub

Sub MonoMe(Btn)
	Dim track : Set track = SDB.Database.QuerySongs("Songs.ID=" & Btn.Common.Hint ).Item	
	If track.Custom3 = "" Then  
		track.Custom3 = "(>m)"
	ElseIf InStr(track.Custom3, "(>m)") = 0 Then
		track.Custom3 = track.Custom3 & "; (>m)"
	End If
	track.WriteTags : track.UpdateDB
	Set track = Nothing
end sub

Sub PLAY1(Btn)
	PlayMain Btn.Common.Hint, 0
end sub

Sub PLAY2(Btn)	
	PlayMain Btn.Common.Hint, 30000
end sub

Sub PLAY3(Btn)
	PlayMain Btn.Common.Hint, 45000
end sub

Sub PLAYHALF(Btn)
	PlayMain Btn.Common.Hint, "half"
end sub

Sub PLAY4(Btn)
	PlayMain Btn.Common.Hint, "end"
end sub
	
Sub PlayMain(SongID, timing)
	Dim track, fixedtime
	Set track = SDB.Database.QuerySongs("Songs.ID=" & SongID ).Item
   SDB.Player.PlaylistAddTrack(track)
   SDB.Player.CurrentSongIndex = SDB.Player.CurrentSongList.Count-1
	
	If timing = "end" Then
		fixedtime = track.SongLength - 9000
	ElseIf timing = "half" Then
		fixedtime = Int(track.SongLength / 2)
	Else
		fixedtime = timing + ( DicOffset.Item(CStr(SongID)) * 1000 )
	end if
	
	If fixedtime > track.SongLength - 4000 Then fixedtime = track.SongLength - 4000	
	If fixedtime < 0 Then fixedtime = 0	
	
	SDB.Player.CurrentSong.StartTime = fixedtime
	SDB.Player.Play	
	Set track = Nothing	
end sub

sub OffsetMinus(Btn)
	DicOffset.Item(CStr(Btn.Common.Hint)) = DicOffset.Item(CStr(Btn.Common.Hint)) - 1
	MakeTheEntries
end sub

sub OffsetPlus(Btn)	
	DicOffset.Item(CStr(Btn.Common.Hint)) = DicOffset.Item(CStr(Btn.Common.Hint)) + 1
	MakeTheEntries
end sub

Sub ColorChange(Btn) '= edit box changes
	Btn.Common.FontColor = GetVbColor( "red" )
End sub

Function GetVbColor( color )
	If color = "fushia" Then GetVbColor = &HF5E72C
	If color = "white" Then GetVbColor = &HFFFFFF
	If color = "grass" Then GetVbColor = &H20BFBB
	If color = "brown" Then GetVbColor = &H2695B9
	If color = "mint" Then GetVbColor = &HD5FFF0
	If color = "pink" Then GetVbColor = &HFFAEFF 
	If color = "ochre" Then GetVbColor = &H05CFDA 
	If color = "red" Then GetVbColor = &H0000FF
	If color = "gold" Then GetVbColor = &H0F87FF
	If color = "clay" Then GetVbColor = &H62B0FF
	If color = "blue" Then GetVbColor = &HFF8000
	If color = "yellow" Then GetVbColor = &H40FFFF 
	If color = "green" Then GetVbColor = &H2CD807
end function

Sub Quit(Btn)
	DuppyForm.Common.Visible = False 
	SDB.Objects("Duppy") = Nothing	
	Set Panel_1 = Nothing : Set Panel_2 = Nothing 
	Set Panel_html = Nothing 
	Set Panel_x = Nothing
	Set DuppyForm = Nothing	
	Set CurrentSong = Nothing
	Set SongList = Nothing
	Set TheSong = Nothing
	Set Song = Nothing
	Set FullArt = Nothing
	Set AlbumArt = Nothing
	Set Image = Nothing
	Set TmpFile = Nothing
	Set ImageNew = Nothing
	Set ArtForm = Nothing
	Set Webby = Nothing
	Set WebBrowser = Nothing
	Set QueryResults = Nothing
	Set CheckedSongs = Nothing
	Set track = Nothing
	Set SourceTrack = Nothing
	Set DicOffset = Nothing
	
	Script.UnregisterEvents SDB 
End Sub

sub KaraokeChecked
	If MatchGenre = "karaoke" Then Panel_1.Common.ChildControl("AllowKaroke").Checked = True
end sub

sub IncludeAlsoT(Btn)	
end sub
sub IncludeAlsoA(Btn)	
end sub

Peke
Posts: 12003
Joined: Tue Jun 10, 2003 7:21 pm
Location: Serbia
Contact:

Re: DUPPY CONQUEROR script (MM4 2016)

Post by Peke » Thu Sep 29, 2016 1:12 pm

Nice addition script.

Have you considered creating MMIP http://www.mediamonkey.com/wiki/index.p ... n_Packages and publish it on MMW addons site http://www.mediamonkey.com/addons/ ?
Best regards,
Pavle
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
How to add SCREENSHOTS to forum

NewtonBoy
Posts: 134
Joined: Tue Nov 23, 2010 1:52 pm

Re: DUPPY CONQUEROR script (MM4 2016)

Post by NewtonBoy » Sun Oct 02, 2016 7:52 am

Nice work! This looks really close to what I want to do, and I intend to look a bit more closely.

Are you intending to develop this any further, or are you just releasing this into the wild for other people to start from?
Media Monkey Gold 4.1.14.1813 Portable
Windows 10 anniversary, i5, 8GB Ram, 256GB SSD, Library on External drive
14MB Media Monkey Database
929 GB Library

Just Guessing
Posts: 64
Joined: Mon Sep 03, 2012 12:06 pm

Re: DUPPY CONQUEROR script (MM4 2016)

Post by Just Guessing » Mon Oct 03, 2016 8:59 pm

Hi. Answer=both.

I have improved two important aspects already and will post new v5 code shortly. Beyond that honestly, I'm just perhaps resolving bugs. (script is doing almost exactly what I want it to do)

What I don't see myself doing any time soon, is generating a big option page to set form size and setting tag/display choices... So I'm afraid at this point this is a script for code tweakers. I'll certainly try to reply to questions about what the code is designed to do, and where one would head to make changes.

m_bojangles
Posts: 98
Joined: Fri Jun 11, 2004 8:22 pm

Re: DUPPY CONQUEROR script (MM4 2016)

Post by m_bojangles » Wed Nov 30, 2016 11:30 am

This looks very interesting. Will you be posting the v5 code soon?

Post Reply