Please note that you should only run this script if you have tracks where the BPM has been calculated. If you do not have any (in the filter selected) then this will cause Auto DJ to cease functioning. However, they do not all need to have BPM values, the tracks without will simply be ignored and never selected.
As always, the installer can be downloaded from my website, which is linked to in my signature. And here is the code...
Code: Select all
'
' MediaMonkey Script
'
' NAME: AutoBeatsDJ 1.4
'
' AUTHOR: trixmoto (http://trixmoto.net)
' DATE : 12/07/2012
'
' INSTALL: Copy to Scripts directory
'
' FIXES: Added option to not favour unplayed tracks  
'        Added option to exclude last X played tracks
'
Option Explicit 
Dim Filters()
Dim Debug : Debug = False
Dim FilterName : FilterName = "- No Filter -"
Dim FilterSQL : FilterSQL = ""
Dim Tolerance : Tolerance = 10
Dim Wandering : Wandering = 1
Dim Unplayed : Unplayed = True
Dim History : History = 50
Sub Install()
  'set default values
  Dim ini : Set ini = SDB.IniFile     
  If ini.StringValue("AutoBeatsDJ","FilterName") = "" Then
    ini.StringValue("AutoBeatsDJ","FilterName") = FilterName
  End If  
  If ini.StringValue("AutoBeatsDJ","Tolerance") = "" Then
    ini.IntValue("AutoBeatsDJ","Tolerance") = Tolerance
  End If
  If ini.StringValue("AutoBeatsDJ","Wandering") = "" Then
    ini.IntValue("AutoBeatsDJ","Wandering") = Wandering
  End If   
  If ini.StringValue("AutoBeatsDJ","Unplayed") = "" Then
    ini.BoolValue("AutoBeatsDJ","Unplayed") = Unplayed
  End If   
  If ini.StringValue("AutoBeatsDJ","History") = "" Then
    ini.IntValue("AutoBeatsDJ","History") = History
  End If  
  'add ini entries
  Set ini = SDB.Tools.IniFileByPath(SDB.ApplicationPath&"Scripts\Scripts.ini")
  If Not (ini Is Nothing) Then
    ini.StringValue("AutoBeatsDJ","Filename") = "AutoBeatsDJ.vbs"
    ini.StringValue("AutoBeatsDJ","DisplayName") = "Auto Beats DJ"
    ini.StringValue("AutoBeatsDJ","Description") = "An AutoDJ which selects similar BPM"
    ini.StringValue("AutoBeatsDJ","Language") = "VBScript"
    ini.StringValue("AutoBeatsDJ","ScriptType") = "4"
    SDB.RefreshScriptItems
  End If     
  If Debug Then
    Call clear()
  End If  
  Set SDB.Objects("AutoBeatsData") = Nothing
End Sub
Sub InitConfigSheet(Sheet)
  Dim ui : Set ui = SDB.UI
  Dim ini : Set ini = SDB.IniFile
  FilterName = ini.StringValue("AutoBeatsDJ","FilterName")
  Tolerance = ini.IntValue("AutoBeatsDJ","Tolerance")
  Wandering = ini.IntValue("AutoBeatsDJ","Wandering")   
  Unplayed = ini.BoolValue("AutoBeatsDJ","Unplayed")
  History = ini.IntValue("AutoBeatsDJ","History")  
  
  Dim edt : Set edt = ui.NewLabel(Sheet)
  edt.Common.SetRect 0, 6, 50, 20
  edt.Caption = "Filter:"
  edt.Autosize = False
  
  Set edt = ui.NewDropDown(Sheet)
  edt.Common.SetRect 34, 3, 150, 20
  edt.Style = 2
  edt.Common.ControlName = "ABDJFilterName"
  Call CreateFiltersArray()
  Call FillDropDownFromArray(edt,Filters)
  edt.ItemIndex = GetFiltersArrayID(FilterName)
  Set edt = ui.NewLabel(Sheet)
  edt.Common.SetRect 194, 6, 50, 20
  edt.Caption = "±BPM:"
  edt.Autosize = False
  Set edt = ui.NewSpinEdit(Sheet)
  edt.Common.SetRect 232, 3, 40, 20
  edt.Common.ControlName = "ABDJTolerance"
  edt.MinValue = 0
  edt.MaxValue = 99
  edt.Value = Tolerance
  
  Set edt = ui.NewLabel(Sheet)
  edt.Common.SetRect 283, 6, 50, 20
  edt.Caption = "Wandering:"
  edt.Autosize = False
  Set edt = ui.NewSpinEdit(Sheet)
  edt.Common.SetRect 345, 3, 40, 20
  edt.Common.ControlName = "ABDJWandering"
  edt.MinValue = 1
  edt.MaxValue = 99
  edt.Value = Wandering  
  
  Set edt = ui.NewLabel(Sheet)
  edt.Common.SetRect 397, 6, 150, 20
  edt.Caption = "Exclude last played:"
  edt.Autosize = False
  Set edt = ui.NewSpinEdit(Sheet)
  edt.Common.SetRect 500, 3, 40, 20
  edt.Common.ControlName = "ABDJHistory"
  edt.MinValue = 1
  edt.MaxValue = 99
  edt.Value = History  
  
  Set edt = ui.NewCheckbox(Sheet)
  edt.Common.SetRect 0, 25, 110, 20
  edt.Common.ControlName = "ABDJUnplayed"
  edt.Caption = "Favour unplayed?"
  edt.Checked = Unplayed  
End Sub
 
Sub CloseConfigSheet(Sheet,SaveConfig)
  If SaveConfig Then
    Dim ini : Set ini = SDB.IniFile
    Dim edt : Set edt = Sheet.Common.ChildControl("ABDJFilterName")
    ini.StringValue("AutoBeatsDJ","FilterName") = edt.ItemText(edt.ItemIndex)
    ini.IntValue("AutoBeatsDJ","Tolerance") = Sheet.Common.ChildControl("ABDJTolerance").Value
    ini.IntValue("AutoBeatsDJ","Wandering") = Sheet.Common.ChildControl("ABDJWandering").Value
	ini.BoolValue("AutoBeatsDJ","Unplayed") = Sheet.Common.ChildControl("ABDJUnplayed").Checked
	ini.IntValue("AutoBeatsDJ","History") = Sheet.Common.ChildControl("ABDJHistory").Value
    Set SDB.Objects("AutoBeatsData") = Nothing
    If Debug Then
      Call clear()
    End If
  End If
End Sub
Function GenerateNewTrack()
  Set GenerateNewTrack = Nothing
  If Debug Then
    Call out("GenerateNewTrack")
  End If      
  Dim iter : Set iter = Nothing
  Dim dic : Set dic = SDB.Objects("AutoBeatsData")
  If dic Is Nothing Then
    Set dic = CreateObject("Scripting.Dictionary")
    dic.Item("cur") = 0
    dic.Item("dir") = 0
    dic.Item("tol") = SDB.IniFile.IntValue("AutoBeatsDJ","Tolerance")
    dic.Item("wan") = SDB.IniFile.IntValue("AutoBeatsDJ","Wandering")
	dic.Item("unp") = SDB.IniFile.IntValue("AutoBeatsDJ","Unplayed")
	dic.Item("lst") = SDB.IniFile.IntValue("AutoBeatsDJ","History")
    dic.Item("sql") = GetFilterSQL()
    Set iter = SDB.Database.OpenSQL("SELECT MIN(Songs.BPM),MAX(Songs.BPM) FROM Songs WHERE Songs.ID>0 "&dic.Item("sql"))
    dic.Item("min") = Int(iter.ValueByIndex(0))
    dic.Item("max") = Int(iter.ValueByIndex(1))
    Set iter = Nothing    
    If Debug Then
      Call out("Tolerance="&dic.Item("tol"))
      Call out("Wandering="&dic.Item("wan"))
	  Call out("Unplayed= "&dic.Item("wan"))
	  Call out("History=  "&dic.Item("wan"))
      Call out("Min BPM=  "&dic.Item("min"))
      Call out("Max BPM=  "&dic.Item("max"))
    End If    
  End If
  Randomize
  Dim cur : cur = Int(dic.Item("cur"))
  Dim dir : dir = Int(dic.Item("dir")) 
  If cur = 0 Then
    cur = Int(Int(dic.Item("wan"))*Rnd)+1
    dir = 0
  End If
  If dir = 0 Then
    dir = Int(3*Rnd)-1
    dic.Item("dir") = dir
  End If
  If Debug Then
    Call out("Current=  "&cur)
    Call out("Direction="&dir)
  End If      
  Dim tol : tol = Int(dic.Item("tol"))
  Dim lst : lst = Int(dic.Item("lst"))
  Dim sql : sql = "SELECT Songs.ID FROM Songs WHERE Songs.ID NOT IN (0"
  Dim list : Set list = SDB.Player.CurrentSongList
  Dim itm : Set itm = Nothing
  Dim i : i = 0
  Dim j : j = 0
  If list.Count > lst Then
    j = list.Count-lst-1
  End If
  For i = j To list.Count-1
    Set itm = list.Item(i)
    sql = sql&","&itm.ID
  Next   
  sql = sql&") "&dic.Item("sql")
  While (tol < 100)
    Dim sql2 : sql2 = ""
    If Not (itm Is Nothing) Then
      If Debug Then
        Call out("Cur BPM=  "&itm.BPM)
      End If        
      If itm.BPM < 0 Then
        sql2 = sql2&" AND Songs.BPM>-1"
      Else
        Dim bpm : bpm = itm.BPM+Int(dir*(tol/2)) 'apply direction
        If tol = 0 Then
          sql2 = sql2&" AND Songs.BPM="&bpm
        Else
          sql2 = sql2&" AND Songs.BPM>="&(bpm-tol)&" AND Songs.BPM<="&(bpm+(tol/2))
        End If    
      End If
    End If
	If Int(dic.Item("unp")) = 1 Then
      sql2 = sql&sql2&" ORDER BY PlayCounter,Random() LIMIT 1"    
	Else
	  sql2 = sql&sql2&" ORDER BY Random() LIMIT 1" 
	End If
    If Debug Then
      Call out("#"&sql2)
    End If                  
    Set iter = SDB.Database.OpenSQL(sql2)
    If iter.EOF Then
      If itm.BPM < 0 Then
        tol = 100
      Else
        tol = tol+Int(dic.Item("tol")) 'increase tolerance
      End If
    Else
      Set iter = SDB.Database.QuerySongs("Songs.ID="&iter.ValueByIndex(0))
      Set GenerateNewTrack = iter.Item
      tol = 100 'exit while
    End If
    Set iter = Nothing
  WEnd
  If GenerateNewTrack Is Nothing Then
	If Int(dic.Item("unp")) = 1 Then
      sql = sql&" ORDER BY PlayCounter,Random() LIMIT 1"    
	Else
	  sql = sql&" ORDER BY Random() LIMIT 1" 
	End If  
    If Debug Then
      Call out("#"&sql)
    End If                    
    Set iter = SDB.Database.OpenSQL(sql)
    If Not (iter.EOF) Then
      Set iter = SDB.Database.QuerySongs("Songs.ID="&iter.ValueByIndex(0))
      Set GenerateNewTrack = iter.Item
    End If
    Set iter = Nothing
  End If
  If Debug Then
    If GenerateNewTrack Is Nothing Then
      Call out(">Nothing")
    Else
      Call out(">"&GenerateNewTrack.ID&"="&GenerateNewTrack.BPM)
    End If
  End If  
  dic.Item("cur") = cur-1
  Set SDB.Objects("AutoBeatsData") = dic
End Function
Function GetFilterID(Name)
  Dim nam : nam = Replace(Name,"'","''")
  If SDB.Database.OpenSQL("SELECT COUNT(*) FROM Filters WHERE Name='"&nam&"'").ValueByIndex(0) = 0 Then
    FilterName = "- No Filter -"
    SDB.IniFile.StringValue("AdvancedReport","FilterName") = FilterName
    GetFilterID = -1
  Else
    GetFilterID = SDB.Database.OpenSQL("SELECT ID FROM Filters WHERE Name='"&name&"'").ValueByIndex(0)
  End If
End Function
Sub FillDropDownFromArray(DropDown,SourceArray)
  Dim i : i = 0
  For i = 0 To UBound(SourceArray)
    Call DropDown.AddItem(SourceArray(i))
  Next
End Sub
Sub CreateFiltersArray()
  Redim Filters(SDB.Database.OpenSQL("SELECT COUNT(*) FROM Filters").ValueByIndex(0)+1)
  Filters(0) = "- No Filter -"
  Filters(1) = "- Active Filter -"
  Dim i : i = 2
  Dim iter : Set iter = SDB.Database.OpenSQL("SELECT Name FROM Filters ORDER BY Pos")
  Do While Not iter.EOF
    Filters(i) = iter.StringByIndex(0)
    i = i+1
    iter.Next
  Loop
  Set iter = Nothing
End Sub
Function GetFiltersArrayID(Name)
  GetFiltersArrayID = 0
  Dim i : i = 0
  For i = 0 To UBound(Filters)
    If Filters(i) = Name Then
      GetFiltersArrayID = i
      Exit For
    End If
  Next 
End Function
Function GetFilterSQL()
  Dim Name : Name = SDB.IniFile.StringValue("AutoBeatsDJ","FilterName")
  Select Case Name
    Case "- No Filter -"
      GetFilterSQL = ""
    Case "- Active Filter -"
      GetFilterSQL = SDB.Database.ActiveFilterQuery
    Case Else
      Dim id : id = GetFilterID(Name)
      If id = -1 Then
        GetFilterSQL = ""
      Else
        GetFilterSQL = SDB.Database.GetFilterQuery(id)
      End If
  End Select
  If Not (GetFilterSQL = "") Then
    GetFilterSQL = "AND "&GetFilterSQL
  End If   
End Function
Sub clear()
  Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
  Dim loc : loc = SDB.TemporaryFolder&"\AutoBeatsDJ.log"
  Dim logf : Set logf = fso.CreateTextFile(loc,True)
  Call logf.Close()
End Sub
Sub out(txt)
  Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
  Dim loc : loc = SDB.TemporaryFolder&"\AutoBeatsDJ.log"
  Dim logf : Set logf = fso.OpenTextFile(loc,8,True)
  Call logf.WriteLine(SDB.ToAscii(txt))
  Call logf.Close()
End Sub



 
 