LinkedTracks v1.1.1 [MM2+3+4] (TSFKA TiedSongsGroups)

Download and get help for different MediaMonkey for Windows 4 Addons.

Moderators: Peke, Gurus

Davo
Posts: 435
Joined: Tue Nov 06, 2007 9:00 pm
Location: Australia

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Davo »

Message from Guest is mine - Login must have timed out

Regards
David
____________________________
Windows 10
MM 5 Beta
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

It crossed my mind to deal with an empty Now Playing list, but I always have something in it.

I modified the script to handle this. But I had to play with it quite a bit. While trying the script with a very small playlist as the source I noticed that when more than one track is added at once (like when you start with an empty playlist and ask AutoDJ to maintain 10 tracks), the first track is not added to the playlist before calling the function for the second track. It's like AutoDJ calls X times the GenerateNewTrack function and then adds all the tracks to Now Playing. So I can't rely on the last track in Now Playing like I did. Which caused what you saw: the same track added multiple times. This happened when the last track in Now Playing was linked, and AutoDJ had to add many tracks, all the calls to GenerateNewTrack returned the same track based on the last in Now Playing (since it did not change between calls)...

So I added a global variable to know which was the last song added, and tweaked the script to avoid adding a track already in Now Playing. It seems to work pretty well. But there might still be cases where you get the same song more than once, depending on how many songs must be added at once and how big is your source playlist. If you do experience this problem, please let me know how many songs are in your Now Playing, what was the current song, how many AutoDJ had to maintain, and what was the source playlist (how many songs, and how many linked).

Code: Select all

'==========================================================================
'
' MediaMonkey Script
'
' NAME: DJTiedSongsGroups
' DESCRIPTION:
'  Lets you use auto-dj while playing together groups of songs that should go together 
'  (groups of songs must previously be tagged as linked)
'
' AUTHOR: Tanguy Kervahut
' DATE  : 11.10.2008
'
' INSTALL:
' - Copy script to MediaMonkey's "Scripts" folder
' - Add an script entry to file Scripts.ini (example shown below)
'
' USE:
' For songs you want in one group, change the Custom3 field for these songs to
'  the same value, beginning with LT (this indicates a "linked track").
' E.g. for an album "Pink Floyd - Dark Side of the Moon" you can change the Custom3 field
'  for all tracks to "LT Pink Floyd - Dark Side of the Moon". (without quotation marks).
' Bear in mind that shorter values for the Custom3 field are faster (so better "LT PF-DSOTM")
' Order of tracks in a tied group is indicated using the standard Track Number field.
'
' [DJTiedSongsGroups]
' FileName=DJTiedSongsGroups.vbs
' DisplayName=AutoDJ Tied songs groups
' Language=VBScript
' ScriptType=4

'##############################################################################################

Option Explicit

Public TagGroupPlaylist, LastSong
 
Sub InitConfigSheet(Panel)
  Dim Edt, Lists, i
  
  Set Edt = SDB.UI.NewLabel(Panel)
  Edt.Common.SetRect 1, 1, 75, 20
  Edt.Caption = "Use playlist:"
  Edt.Autosize = False
  Edt.Alignment = 0

  Set Edt = SDB.UI.NewDropDown(Panel)
  Set Lists = SDB.PlaylistByTitle("").ChildPlaylists
  for i = 0 to Lists.Count-1
     Edt.AddItem(Lists.Item(i).Title)
  next
  Edt.Common.SetRect 86, 1, 200, 20
  Edt.Common.ControlName = "TagGroupPlaylist"
  Edt.Text = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
End Sub
 

Sub CloseConfigSheet(Panel, SaveConfig)
  if Saveconfig then
     SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist") = Panel.Common.ChildControl("TagGroupPlaylist").Text
  end if
End Sub
 
 
Function GenerateNewTrack
  Dim LastGroup, NextSong, NextFound

  NextFound = false
  
  if isEmpty(LastSong) AND SDB.Player.PlaylistCount > 0 then
    Set LastSong = SDB.Player.PlaylistItems(SDB.Player.PlaylistCount - 1)
  end if
  
  if NOT isEmpty(LastSong) then
    If Left(LastSong.Custom3, 2) = "LT" Then
      Set LastGroup = SDB.Database.QuerySongs("Songs.Custom3='" & LastSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
  
      Do While Not LastGroup.EOF
        if LastGroup.Item.TrackOrder > LastSong.TrackOrder then
	       Set NextSong = LastGroup.Item
		   NextFound = true
  	       exit do
        end if
        LastGroup.Next
      Loop
    end if
  end if
  
  If NextFound Then
    Set LastSong = NextSong
	Set GenerateNewTrack = NextSong
  else
    Dim CheckPlaylist, RandomTrack, i
	
	TagGroupPlaylist = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
    Set CheckPlaylist = SDB.PlaylistByTitle(TagGroupPlaylist).Tracks
	i = 0
	Do
	  RandomTrack = Int((Rnd() * CheckPlaylist.Count) + 1)
	  Set NextSong = CheckPlaylist.Item(RandomTrack)
	  i = i + 1
	Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, LastSong)) AND i < CheckPlaylist.Count 
	
	If Left(NextSong.Custom3, 2) = "LT" Then
      Set LastGroup = SDB.Database.QuerySongs("Songs.Custom3='" & NextSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
      Set LastSong = LastGroup.Item
      Set GenerateNewTrack = LastGroup.Item
    else
      Set LastSong = NextSong
      Set GenerateNewTrack = NextSong
	end if
  End If
  
End Function


Function IsInSongList( Song, List )
  Dim i
   
  IsInSongList = False
  if not IsEmpty(Song) AND List.Count > 0 then
  for i = 0 to List.Count -1
    if List.Item(i).SongId = Song.SongId then
	  IsInSongList = True
	  exit for
	end if 
  next
  end if
    
End Function

Function SameGroup( Song1, Song2 )
  if isEmpty(Song1) or isEmpty(Song2) then
    SameGroup = False
  else	
    if Song1.SongId <> Song2.SongId AND (Left(Song1.Custom3, 2) <> "LT" OR Song1.Custom3 <> Song2.Custom3) then
	   SameGroup = False
	else
	   SameGroup = True
    end if
  end if
    
End Function
Let me know how it goes

Rycher
Davo
Posts: 435
Joined: Tue Nov 06, 2007 9:00 pm
Location: Australia

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Davo »

Thanks Rycher for spending the time on this. Your amended script seems to have fixed all the issues.
FYI I'm testing with a playlist that has 7 Albums, 83 Tracks. One album has 2 groupings (1-3 & 4-6). AutoDJ is set to maintain at least 10 tracks.

Regards
David
____________________________
Windows 10
MM 5 Beta
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

Glad you enjoy it.

There is a limitation I forgot to mention with the modified script. Like I explained, when AutoDJ adds multiple tracks at once, the Now Playing list is only updated after all the calls to the script. So I can't rely on the last track in Now Playing for linked tracks. Instead, I keep the last track added in a variable, this way the script always know what was added previously. But because of this, it won't consider tracks you would add manually.

For example, if the Now Playing list currently ends with half the tracks of a group (added by the script), and you manually add something different after this, the script will add the rest of the group after the track you added manually. But I'm not sure what should be the right behaviour in this situation. When you mix manual selection with an AutoDJ that tries to be intelligent, you're bound to mess up the intelligence.

Rycher
Davo
Posts: 435
Joined: Tue Nov 06, 2007 9:00 pm
Location: Australia

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Davo »

Not quite sure what you mean by "add tracks manually". Do you mean to literally add a track in addition to the tracks AutoDJ has selected? - I've never done this & in fact I didn't realise you could. I just let AutoDJ do all the selecting from the Library or Playlist set up in Options then automatically play thru them.

The only issue i'm having at the moment with my test playlist (83 tracks) is that after about 30 tracks Auto DJ stops selecting tracks & your script gives an error message because it can't find 'song'. Maybe AutoDJ needs a bigger playlist.

Times like this I wish i knew more about Scripts, sadly, thats not going to happen in a hurry.

Regards
David
____________________________
Windows 10
MM 5 Beta
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

For manual, yeah that's what I meant, if you decide to add something else from the library to Now Playing. Like at work, I mainly use AutoDJ, but from time to time I had whole albums I want to listen to manually. AutoDJ simply insures that your playlist does not get empty, it does not prevent you from adding whatever you want manually.

For the script: I've done one little improvement, a call to Randomize at the beginning to change the sequence of random numbers (otherwise it was always filling Now Playing the same way). I've also done a correction: the random index was off by one, so it could try to access an index outside the range. I.e. in your case at some point it tried to access track 84 out of 83. And it always occured after the same number of tracks since the random sequence was always the same.

So now it should not give you an error, and the random sequence will really be random from one time to the next.

Code: Select all

'==========================================================================
'
' MediaMonkey Script
'
' NAME: DJTiedSongsGroups
' DESCRIPTION:
'  Lets you use auto-dj while playing together groups of songs that should go together 
'  (groups of songs must previously be tagged as linked)
'
' AUTHOR: Tanguy Kervahut
' DATE  : 11.10.2008
'
' INSTALL:
' - Copy script to MediaMonkey's "Scripts" folder
' - Add an script entry to file Scripts.ini (example shown below)
'
' USE:
' For songs you want in one group, change the Custom3 field for these songs to
'  the same value, beginning with LT (this indicates a "linked track").
' E.g. for an album "Pink Floyd - Dark Side of the Moon" you can change the Custom3 field
'  for all tracks to "LT Pink Floyd - Dark Side of the Moon". (without quotation marks).
' Bear in mind that shorter values for the Custom3 field are faster (so better "LT PF-DSOTM")
' Order of tracks in a tied group is indicated using the standard Track Number field.
'
' [DJTiedSongsGroups]
' FileName=DJTiedSongsGroups.vbs
' DisplayName=AutoDJ Tied songs groups
' Language=VBScript
' ScriptType=4

'##############################################################################################

Option Explicit

Public TagGroupPlaylist, LastSong
 
Sub InitConfigSheet(Panel)
  Dim Edt, Lists, i
  
  Set Edt = SDB.UI.NewLabel(Panel)
  Edt.Common.SetRect 1, 1, 75, 20
  Edt.Caption = "Use playlist:"
  Edt.Autosize = False
  Edt.Alignment = 0

  Set Edt = SDB.UI.NewDropDown(Panel)
  Set Lists = SDB.PlaylistByTitle("").ChildPlaylists
  for i = 0 to Lists.Count-1
     Edt.AddItem(Lists.Item(i).Title)
  next
  Edt.Common.SetRect 86, 1, 200, 20
  Edt.Common.ControlName = "TagGroupPlaylist"
  Edt.Text = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
End Sub
 

Sub CloseConfigSheet(Panel, SaveConfig)
  if Saveconfig then
     SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist") = Panel.Common.ChildControl("TagGroupPlaylist").Text
  end if
End Sub
 
 
Function GenerateNewTrack
  Dim LastGroup, NextSong, NextFound

  NextFound = false
  
  if isEmpty(LastSong) then
    Randomize
    if SDB.Player.PlaylistCount > 0 then
      Set LastSong = SDB.Player.PlaylistItems(SDB.Player.PlaylistCount - 1)
    end if
  end if
  
  if NOT isEmpty(LastSong) then
    If Left(LastSong.Custom3, 2) = "LT" Then
      Set LastGroup = SDB.Database.QuerySongs("Songs.Custom3='" & LastSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
  
      Do While Not LastGroup.EOF
        if LastGroup.Item.TrackOrder > LastSong.TrackOrder then
	       Set NextSong = LastGroup.Item
		   NextFound = true
  	       exit do
        end if
        LastGroup.Next
      Loop
    end if
  end if
  
  If NextFound Then
    Set LastSong = NextSong
	Set GenerateNewTrack = NextSong
  else
    Dim CheckPlaylist, RandomTrack, i
	
	TagGroupPlaylist = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
    Set CheckPlaylist = SDB.PlaylistByTitle(TagGroupPlaylist).Tracks
	i = 0
	Do
	  RandomTrack = Int(Rnd() * CheckPlaylist.Count)
	  Set NextSong = CheckPlaylist.Item(RandomTrack)
	  i = i + 1
	Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, LastSong)) AND i < CheckPlaylist.Count 
	
	If Left(NextSong.Custom3, 2) = "LT" Then
      Set LastGroup = SDB.Database.QuerySongs("Songs.Custom3='" & NextSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
      Set LastSong = LastGroup.Item
      Set GenerateNewTrack = LastGroup.Item
    else
      Set LastSong = NextSong
      Set GenerateNewTrack = NextSong
	end if
  End If
  
End Function


Function IsInSongList( Song, List )
  Dim i
   
  IsInSongList = False
  if not isEmpty(Song) AND List.Count > 0 then
  for i = 0 to List.Count -1
    if List.Item(i).SongId = Song.SongId then
	  IsInSongList = True
	  exit for
	end if 
  next
  end if
    
End Function

Function SameGroup( Song1, Song2 )
  if isEmpty(Song1) or isEmpty(Song2) then
    SameGroup = False
  else	
    if Song1.SongId <> Song2.SongId AND (Left(Song1.Custom3, 2) <> "LT" OR Song1.Custom3 <> Song2.Custom3) then
	   SameGroup = False
	else
	   SameGroup = True
    end if
  end if
    
End Function
Davo
Posts: 435
Joined: Tue Nov 06, 2007 9:00 pm
Location: Australia

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Davo »

Thanks for the update - The latest script works like a charm. I've run it for about 4 hours now without any problems.
Again I appreciate your work on this.

Regards
David
____________________________
Windows 10
MM 5 Beta
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

Here is an updated version of my script, with a new "by album" option. Basically it treats 2 types of groups: specifically linked songs, and whole albums, but the basic functionnality is the same.

The first versions I did with the album option worked the same as the old script, but I didn't like the fact that if I switched album mode on or off, I could stop playing an album halfway through (switching to auto-dj by track) or start adding tracks from the same album without having played the first tracks (switching to album mode). I played with INI variables, but it made the script a bit complicated for nothing I thought. Until I realized one thing: auto-dj calls this function to get one track each time it wants to add one track; but nothing prevents the script from adding as many tracks as needed directly at the end of Now playing (and not return anything - this does not bother auto-dj). The only thing is that if auto-dj needs to add multiple tracks at the same time, it calls the script as many times as needed at once (i.e. before updating Now playing). So to avoid adding multiple groups (at worst multiple albums) at once, there a bit of "dirty" code to handle that situation. So in the end it will at least add the number of tracks specified in the auto-dj config, and at most one group can make the number of tracks added go over the max specified.

So here it is:

Code: Select all

'==========================================================================
'
' MediaMonkey Script
'
' NAME: DJTiedSongsGroups
' DESCRIPTION:
'  Lets you use auto-dj while playing together groups of songs that should go together
'  (groups of songs must previously be tagged as linked)
'
' AUTHOR: Tanguy Kervahut
' DATE  : 11.10.2008
'
' Modified: 29.10.2008
'    -Added "By album" option
'    -Change the mechanism, it now adds a whole group (or album) at once. So it can add more tracks than the maximum specified for auto-dj when
'      a group has more tracks than the maximum.
'
' INSTALL:
' - Copy script to MediaMonkey's "Scripts" folder
' - Add an script entry to file Scripts.ini (example shown below)
'
' USE:
' For songs you want in one group, change the Custom3 field for these songs to
'  the same value, beginning with LT (this indicates a "linked track").
' E.g. for an album "Pink Floyd - Dark Side of the Moon" you can change the Custom3 field
'  for all tracks to "LT Pink Floyd - Dark Side of the Moon". (without quotation marks).
' Bear in mind that shorter values for the Custom3 field are faster (so better "LT PF-DSOTM")
' Order of tracks in a tied group is indicated using the standard Track Number field.
'
' [DJTiedSongsGroups]
' FileName=DJTiedSongsGroups.vbs
' DisplayName=AutoDJ Tied songs groups
' Language=VBScript
' ScriptType=4

'##############################################################################################

Option Explicit

Public DJTSG_LastSong, DJTSG_LastCall, DJTSG_NbAdded, Fso, LogF

Sub InitConfigSheet(Panel)
  Dim Edt, Lists, i

  Set Edt = SDB.UI.NewLabel(Panel)
  Edt.Common.SetRect 1, 5, 75, 20
  Edt.Caption = "Use playlist:"
  Edt.Autosize = False
  Edt.Alignment = 0

  Set Edt = SDB.UI.NewDropDown(Panel)
  Set Lists = SDB.PlaylistByTitle("").ChildPlaylists
  for i = 0 to Lists.Count-1
     Edt.AddItem(Lists.Item(i).Title)
  next
  Edt.Common.SetRect 86, 1, 200, 20
  Edt.Common.ControlName = "TagGroupPlaylist"
  Edt.Text = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")

  Set Edt = SDB.UI.NewCheckBox(Panel)
  Edt.Common.SetRect 295, 2, 75, 20
  Edt.Common.ControlName = "ByAlbum"
  Edt.Caption = "By Album"
  Edt.Checked = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
End Sub


Sub CloseConfigSheet(Panel, SaveConfig)
  if Saveconfig then
     SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist") = Panel.Common.ChildControl("TagGroupPlaylist").Text
     SDB.IniFile.BoolValue("TagGroup", "ByAlbum") = Panel.Common.ChildControl("ByAlbum").Checked
  end if
End Sub


Function GenerateNewTrack
  Dim ByAlbum, TagGroupPlaylist, CheckPlaylist, i, RandomTrack, NextSong, NextGroup

  if isEmpty(DJTSG_LastSong) then
    ' Randomize on first run
    Randomize
    DJTSG_NbAdded = 0
    DJTSG_LastCall = DateAdd("n",-1,Now)
  end if

  ' The following is to avoid adding multiple groups when more than one track needs
  ' to be added. Because MM can call this function multiple times at once when more
  ' than one is required to reach the minimum to maintain. When this happens, the
  ' playlist isn't updated until all calls are finished. So from an empty playlist,
  ' it could add 5 albums (if by album and number to maintain is 5).
  if DateDiff("s",DJTSG_LastCall,Now) < 5 then
    DJTSG_NbAdded = DJTSG_NbAdded - 1
    if DJTSG_NbAdded > 0 then
      exit Function
    end if
  else
    DJTSG_NbAdded = 0
  end if

  ByAlbum = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
  TagGroupPlaylist = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
  Set CheckPlaylist = SDB.PlaylistByTitle(TagGroupPlaylist).Tracks

  i = 0
  Do
    RandomTrack = Int(Rnd() * CheckPlaylist.Count)
    Set NextSong = CheckPlaylist.Item(RandomTrack)
    i = i + 1
  Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, DJTSG_LastSong, ByAlbum)) AND i < CheckPlaylist.Count

  If ByAlbum OR Left(NextSong.Custom3, 2) = "LT" Then
    if ByAlbum then
      Set NextGroup = SDB.Database.QuerySongs("Songs.IDAlbum='" & NextSong.Album.Id & "' ORDER BY abs(Songs.TrackNumber) ASC")
    else
      Set NextGroup = SDB.Database.QuerySongs("Songs.Custom3='" & NextSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
    end if
    ' Insert directly whole group at end of Now Playing - return nothing
    Set DJTSG_LastSong = NextGroup.Item
    Do While Not NextGroup.EOF
      DJTSG_NbAdded = DJTSG_NbAdded + 1
      Call SDB.Player.PlaylistAddTrack( NextGroup.Item )
      NextGroup.Next
    Loop
  else
    ' Return track found
    DJTSG_NbAdded = DJTSG_NbAdded + 1
    Set GenerateNewTrack = NextSong
    Set DJTSG_LastSong = NextSong
  end if

  DJTSG_LastCall = Now
End Function


Function IsInSongList( Song, List )
  Dim i

  IsInSongList = False
  if not isEmpty(Song) AND List.Count > 0 then
  for i = 0 to List.Count -1
    if List.Item(i).SongId = Song.SongId then
      IsInSongList = True
      exit for
    end if
  next
  end if
End Function


Function SameGroup( Song1, Song2, ByAlbum )
  if isEmpty(Song1) or isEmpty(Song2) then
    SameGroup = False
  else
    if ByAlbum then
      SameGroup = Song1.Album.Id = Song2.Album.Id
    else
      SameGroup = Song1.SongId = Song2.SongId OR (Left(Song1.Custom3, 2) = "LT" AND Song1.Custom3 = Song2.Custom3)
    end if
  end if
End Function
Also, when in album mode I wanted to know what was the next album coming up. So I made another script: when it arrives on the last track of an album, it pops a window with the next album for a few seconds. See this thread for more details: http://www.mediamonkey.com/forum/viewto ... =2&t=33875
Davo
Posts: 435
Joined: Tue Nov 06, 2007 9:00 pm
Location: Australia

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Davo »

Thanks for this update - I like to shuffle albums so this is great.
Not sure of the difficulty but in addition to Playlist is it possible to broaden the inputs to the script to include Genre filter & Library filter (As in Triximoto's AutoAlbumDJ script).

As a general observation there's quite a few "Auto DJ" type scripts around at the moment. Each with it's own special features. It would be good if the development of the AutoDJ function could be coordinated (Scripters & MM Devs) so that the best of the features could be integrated into a single application within MM. I'm interested in your thoughts on this.

Regards
David
____________________________
Windows 10
MM 5 Beta
Keith M
Posts: 3
Joined: Thu Nov 20, 2008 8:30 am

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Keith M »

This script looks great, but I have tried unsuccessfully to load it numerous times. This is my first script & have done exactly as it says (well obviously I haven't). Is there some basic step to adding this script that I may have missed?

Thanks from a script loading newbie.
Guest

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Guest »

Sorry. I am just bumping this up because I have spent hours trying to make this script work.

I put :

[DJTiedSongsGroups]
FileName=DJTiedSongsGroups.vbs
DisplayName=AutoDJ Tied songs groups
Language=VBScript
ScriptType=4

in the scripts .ini file

and I turned this text into a DJTiedSongGroups.vbs file:


'==========================================================================
'
' MediaMonkey Script
'
' NAME: DJTiedSongsGroups
' DESCRIPTION:
' Lets you use auto-dj while playing together groups of songs that should go together
' (groups of songs must previously be tagged as linked)
'
' AUTHOR: Tanguy Kervahut
' DATE : 11.10.2008
'
' Modified: 29.10.2008
' -Added "By album" option
' -Change the mechanism, it now adds a whole group (or album) at once. So it can add more tracks than the maximum specified for auto-dj when
' a group has more tracks than the maximum.
'
' INSTALL:
' - Copy script to MediaMonkey's "Scripts" folder
' - Add an script entry to file Scripts.ini (example shown below)
'
' USE:
' For songs you want in one group, change the Custom3 field for these songs to
' the same value, beginning with LT (this indicates a "linked track").
' E.g. for an album "Pink Floyd - Dark Side of the Moon" you can change the Custom3 field
' for all tracks to "LT Pink Floyd - Dark Side of the Moon". (without quotation marks).
' Bear in mind that shorter values for the Custom3 field are faster (so better "LT PF-DSOTM")
' Order of tracks in a tied group is indicated using the standard Track Number field.
'
' [DJTiedSongsGroups]
' FileName=DJTiedSongsGroups.vbs
' DisplayName=AutoDJ Tied songs groups
' Language=VBScript
' ScriptType=4

'##############################################################################################

Option Explicit

Public DJTSG_LastSong, DJTSG_LastCall, DJTSG_NbAdded, Fso, LogF

Sub InitConfigSheet(Panel)
Dim Edt, Lists, i

Set Edt = SDB.UI.NewLabel(Panel)
Edt.Common.SetRect 1, 5, 75, 20
Edt.Caption = "Use playlist:"
Edt.Autosize = False
Edt.Alignment = 0

Set Edt = SDB.UI.NewDropDown(Panel)
Set Lists = SDB.PlaylistByTitle("").ChildPlaylists
for i = 0 to Lists.Count-1
Edt.AddItem(Lists.Item(i).Title)
next
Edt.Common.SetRect 86, 1, 200, 20
Edt.Common.ControlName = "TagGroupPlaylist"
Edt.Text = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")

Set Edt = SDB.UI.NewCheckBox(Panel)
Edt.Common.SetRect 295, 2, 75, 20
Edt.Common.ControlName = "ByAlbum"
Edt.Caption = "By Album"
Edt.Checked = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
End Sub


Sub CloseConfigSheet(Panel, SaveConfig)
if Saveconfig then
SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist") = Panel.Common.ChildControl("TagGroupPlaylist").Text
SDB.IniFile.BoolValue("TagGroup", "ByAlbum") = Panel.Common.ChildControl("ByAlbum").Checked
end if
End Sub


Function GenerateNewTrack
Dim ByAlbum, TagGroupPlaylist, CheckPlaylist, i, RandomTrack, NextSong, NextGroup

if isEmpty(DJTSG_LastSong) then
' Randomize on first run
Randomize
DJTSG_NbAdded = 0
DJTSG_LastCall = DateAdd("n",-1,Now)
end if

' The following is to avoid adding multiple groups when more than one track needs
' to be added. Because MM can call this function multiple times at once when more
' than one is required to reach the minimum to maintain. When this happens, the
' playlist isn't updated until all calls are finished. So from an empty playlist,
' it could add 5 albums (if by album and number to maintain is 5).
if DateDiff("s",DJTSG_LastCall,Now) < 5 then
DJTSG_NbAdded = DJTSG_NbAdded - 1
if DJTSG_NbAdded > 0 then
exit Function
end if
else
DJTSG_NbAdded = 0
end if

ByAlbum = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
TagGroupPlaylist = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
Set CheckPlaylist = SDB.PlaylistByTitle(TagGroupPlaylist).Tracks

i = 0
Do
RandomTrack = Int(Rnd() * CheckPlaylist.Count)
Set NextSong = CheckPlaylist.Item(RandomTrack)
i = i + 1
Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, DJTSG_LastSong, ByAlbum)) AND i < CheckPlaylist.Count

If ByAlbum OR Left(NextSong.Custom3, 2) = "LT" Then
if ByAlbum then
Set NextGroup = SDB.Database.QuerySongs("Songs.IDAlbum='" & NextSong.Album.Id & "' ORDER BY abs(Songs.TrackNumber) ASC")
else
Set NextGroup = SDB.Database.QuerySongs("Songs.Custom3='" & NextSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
end if
' Insert directly whole group at end of Now Playing - return nothing
Set DJTSG_LastSong = NextGroup.Item
Do While Not NextGroup.EOF
DJTSG_NbAdded = DJTSG_NbAdded + 1
Call SDB.Player.PlaylistAddTrack( NextGroup.Item )
NextGroup.Next
Loop
else
' Return track found
DJTSG_NbAdded = DJTSG_NbAdded + 1
Set GenerateNewTrack = NextSong
Set DJTSG_LastSong = NextSong
end if

DJTSG_LastCall = Now
End Function


Function IsInSongList( Song, List )
Dim i

IsInSongList = False
if not isEmpty(Song) AND List.Count > 0 then
for i = 0 to List.Count -1
if List.Item(i).SongId = Song.SongId then
IsInSongList = True
exit for
end if
next
end if
End Function


Function SameGroup( Song1, Song2, ByAlbum )
if isEmpty(Song1) or isEmpty(Song2) then
SameGroup = False
else
if ByAlbum then
SameGroup = Song1.Album.Id = Song2.Album.Id
else
SameGroup = Song1.SongId = Song2.SongId OR (Left(Song1.Custom3, 2) = "LT" AND Song1.Custom3 = Song2.Custom3)
end if
end if
End Function

I'm not sure what else I have to do. This script does not appear in the scripts list under the tools dropdown menu in MM.

I entered the same text in Custom Field 3, but when playing back with the Shuffle on, MM does not play them in order. Example: When playing Dark Side of the Moon, the first three tracks should be tied together. They are not.


I have version 3.0.6.1190

Any help would be greatly appreciated!
trixmoto
Posts: 10024
Joined: Fri Aug 26, 2005 3:28 am
Location: Hull, UK
Contact:

Re: TiedSongsGroups: lets you make tied groups of songs

Post by trixmoto »

Script type 4 is the Auto DJ type. This means that you should find that this script appears in the Auto DJ source dropdown as a new option.
Download my scripts at my own MediaMonkey fansite.
All the code for my website and scripts is safely backed up immediately and for free using Dropbox.
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

Here's yet another version of my script. I fixed the "By Album" mode to give an equal chance to all albums. Before, it selected a track at random from the source playlist, and if it was By Album it would play the whole album of the track. Thus albums with more tracks had more chances to play, i.e. a triple live album would come back more often than Thick As A Brick (which only has 2 songs).

I've fixed this so that when in Album mode, it selects an album at random from the albums present in the source playlist, thus giving each album the same chance of being played.

Another thing I added: when the selected album is a multi-disc album, it pop-up a message to ask you if the whole album should play or only the selected disc (telling you which disc was selected at random). I've done this for multi-disc boxed sets when I don't necessarily want to listen to the 4 or more CDs in a row. Multi-disc albums are identified by track numbers being in the hundreeds (101 is CD 1 track 1, 201 is CD 2 track 1, etc). So if you use the disc number field, you need to adapt the script for this to work. If you don't want this simply remove the corresponding block in the script.

Code: Select all

'==========================================================================
'
' MediaMonkey Script
'
' NAME: DJTiedSongsGroups
' DESCRIPTION:
'  Lets you use auto-dj while playing together groups of songs that should go together
'  (groups of songs must previously be tagged as linked)
'
' AUTHOR: Tanguy Kervahut
' DATE  : 11.10.2008
'
' Modified: 29.10.2008
'    -Added "By album" option
'    -Change the mechanism, it now adds a whole group (or album) at once. So it can add more tracks than the maximum specified for auto-dj when
'      a group has more tracks than the maximum.
'
' Modified: 24.02.2009
'    -"By album" option now gives the same weight to all albums (before an album with more tracks had more chances to play)
'    -For multi-disc albums, ask if whole album should play or only selected disc.
'
' INSTALL:
' - Copy script to MediaMonkey's "Scripts" folder
' - Add an script entry to file Scripts.ini (example shown below)
'
' USE:
' For songs you want in one group, change the Custom3 field for these songs to
'  the same value, beginning with LT (this indicates a "linked track").
' E.g. for an album "Pink Floyd - Dark Side of the Moon" you can change the Custom3 field
'  for all tracks to "LT Pink Floyd - Dark Side of the Moon". (without quotation marks).
' Bear in mind that shorter values for the Custom3 field are faster (so better "LT PF-DSOTM")
' Order of tracks in a tied group is indicated using the standard Track Number field.
'
' [DJTiedSongsGroups]
' FileName=DJTiedSongsGroups.vbs
' DisplayName=AutoDJ Tied songs groups
' Language=VBScript
' ScriptType=4

'##############################################################################################

Option Explicit

Public DJTSG_LastSong, DJTSG_LastCall, DJTSG_NbAdded, Fso, LogF

Sub InitConfigSheet(Panel)
  Dim Edt, Lists, i

  Set Edt = SDB.UI.NewLabel(Panel)
  Edt.Common.SetRect 1, 5, 75, 20
  Edt.Caption = "Use playlist:"
  Edt.Autosize = False
  Edt.Alignment = 0

  Set Edt = SDB.UI.NewDropDown(Panel)
  Set Lists = SDB.PlaylistByTitle("").ChildPlaylists
  for i = 0 to Lists.Count-1
     Edt.AddItem(Lists.Item(i).Title)
  next
  Edt.Common.SetRect 86, 1, 200, 20
  Edt.Common.ControlName = "TagGroupPlaylist"
  Edt.Text = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")

  Set Edt = SDB.UI.NewCheckBox(Panel)
  Edt.Common.SetRect 295, 2, 75, 20
  Edt.Common.ControlName = "ByAlbum"
  Edt.Caption = "By Album"
  Edt.Checked = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
End Sub


Sub CloseConfigSheet(Panel, SaveConfig)
  if Saveconfig then
     SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist") = Panel.Common.ChildControl("TagGroupPlaylist").Text
     SDB.IniFile.BoolValue("TagGroup", "ByAlbum") = Panel.Common.ChildControl("ByAlbum").Checked
  end if
End Sub


Function GenerateNewTrack
  Dim ByAlbum, TagGroupPlaylist, CheckPlaylist, i, RandomTrack, NextSong, NextGroup, DiscNo

  if isEmpty(DJTSG_LastSong) then
    ' Randomize on first run
    Randomize
    DJTSG_NbAdded = 0
    DJTSG_LastCall = DateAdd("n",-1,Now)
  end if

  ' The following is to avoid adding multiple groups when more than one track needs
  ' to be added. Because MM can call this function multiple times at once when more
  ' than one is required to reach the minimum to maintain. When this happens, the
  ' playlist isn't updated until all calls are finished. So from an empty playlist,
  ' it could add 5 albums (if by album and number to maintain is 5).
  if DateDiff("s",DJTSG_LastCall,Now) < 5 then
    DJTSG_NbAdded = DJTSG_NbAdded - 1
    if DJTSG_NbAdded > 0 then
      exit Function
    end if
  else
    DJTSG_NbAdded = 0
  end if

  Dim answer
  ByAlbum = SDB.IniFile.BoolValue("TagGroup", "ByAlbum")
  TagGroupPlaylist = SDB.IniFile.StringValue("TagGroup", "DefaultPlaylist")
  Set CheckPlaylist = SDB.PlaylistByTitle(TagGroupPlaylist).Tracks
  if (CheckPlaylist.Count = 0) then
    ' To avoid multiple pop-up, see previous comment
    DJTSG_NbAdded = 99
    answer = SDB.MessageBox( "AutoDJ playlist is empty", mtError, Array(mbOk))
    exit Function
  end if

  i = 0
  if ByAlbum then
     dim CheckAlbumList, NextAlbum, RandomAlbum, AlbumTrackList
     Set CheckAlbumList = CheckPlaylist.Albums
     ' When ByAlbum, select an album at random from the AutoDJ playlist
     ' and not a track, otherwise albums with more tracks get picked more often
     Do
       RandomAlbum = Int(Rnd() * CheckAlbumlist.Count)
       Set NextAlbum = CheckAlbumlist.Item(RandomAlbum)
       Set AlbumTrackList = NextAlbum.Tracks
       RandomTrack = Int(Rnd() * AlbumTrackList.Count)
       Set NextSong = AlbumTrackList.Item(RandomTrack)
       i = i + 1
     Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, DJTSG_LastSong, ByAlbum)) AND i < CheckPlaylist.Count
  else
     Do
       RandomTrack = Int(Rnd() * CheckPlaylist.Count)
       Set NextSong = CheckPlaylist.Item(RandomTrack)
       i = i + 1
     Loop while (IsInSongList(NextSong, SDB.Player.CurrentPlaylist) Or SameGroup(NextSong, DJTSG_LastSong, ByAlbum)) AND i < CheckPlaylist.Count
  end if

  ' If you don't want to be asked what to play when it's a multi-disc album, simply replace the block below by: DiscNo = 0
  if (NextSong.TrackOrderStr <> "") then
     DiscNo = Fix(NextSong.TrackOrderStr / 100)
  else
     DiscNo = 0
  end if
  if (ByAlbum AND DiscNo > 0) then
    ' Ask to play full album or disc only
    answer = SDB.MessageBox( NextSong.AlbumArtistName & Chr(13) & NextSong.AlbumName & Chr(13) & Chr(13) & "Add full album? (No = Disc " & DiscNo & " only)", mtConfirmation, Array(mbYes,mbNo))
    if answer = mrYes then
      DiscNo = 0
    end if
  end if

  If ByAlbum OR Left(NextSong.Custom3, 2) = "LT" Then
    if ByAlbum then
      Set NextGroup = SDB.Database.QuerySongs("Songs.IDAlbum='" & NextSong.Album.Id & "' ORDER BY abs(Songs.TrackNumber) ASC")
    else
      Set NextGroup = SDB.Database.QuerySongs("Songs.Custom3='" & NextSong.Custom3 & "' ORDER BY abs(Songs.TrackNumber) ASC")
    end if
    ' Insert directly whole group at end of Now Playing - return nothing
    Set DJTSG_LastSong = NextGroup.Item
    Do While Not NextGroup.EOF
      if (NOT ByAlbum OR DiscNo = 0 OR Fix(NextGroup.Item.TrackOrderStr / 100) = DiscNo ) then
        DJTSG_NbAdded = DJTSG_NbAdded + 1
        Call SDB.Player.PlaylistAddTrack( NextGroup.Item )
      end if
      NextGroup.Next
    Loop
  else
    ' Return track found
    DJTSG_NbAdded = DJTSG_NbAdded + 1
    Set GenerateNewTrack = NextSong
    Set DJTSG_LastSong = NextSong
  end if

  DJTSG_LastCall = Now
End Function


Function IsInSongList( Song, List )
  Dim i

  IsInSongList = False
  if not isEmpty(Song) AND List.Count > 0 then
  for i = 0 to List.Count -1
    if List.Item(i).SongId = Song.SongId then
      IsInSongList = True
      exit for
    end if
  next
  end if
End Function


Function SameGroup( Song1, Song2, ByAlbum )
  if isEmpty(Song1) or isEmpty(Song2) then
    SameGroup = False
  else
    if ByAlbum then
      SameGroup = Song1.Album.Id = Song2.Album.Id
    else
      SameGroup = Song1.SongId = Song2.SongId OR (Left(Song1.Custom3, 2) = "LT" AND Song1.Custom3 = Song2.Custom3)
    end if
  end if
End Function


Sub logme(msg)
' usage: logme( "text" & VarName )
' Don't forget to define LogF and Fso as Public
'  If DebugSt Then
    If IsEmpty(LogF) Then
      Set Fso = CreateObject("Scripting.FileSystemObject")
      Set LogF = Fso.OpenTextFile(Script.ScriptPath&".log",8,True)
    End If
    LogF.WriteLine Now() & ": " & msg
'  End If
End Sub
rycher
Posts: 129
Joined: Mon Sep 11, 2006 8:24 pm

Re: TiedSongsGroups: lets you make tied groups of songs

Post by rycher »

I've edited my previous post to fix a little bug in the script.
Einstein X

Re: TiedSongsGroups: lets you make tied groups of songs

Post by Einstein X »

Rycher et al,

I'm happy I found this thread on Media Monkey. I have a number of DJ mix albums, which I always want to listen to as full album. Until I found your scripts I used to rip a mix album as one long track so it would play as a whole. The main reason why I did this was that I like to have my media player to just shuffle through all my music all the time and it sucks to listen to one track from the middle of a mix and then shuffle away from the mix again. However I do also like to Scrobble everything I'm listening to, but when I play the full album mp3 the individual songs won't be Scrobbled, making my music library on Last.FM a bit biased towards guitar music.

Now a few weeks ago I've found this function and have been trying out your scripts. It took me a while to find the one that worked for me, but currently I am using Rycher's script posted on Wed Oct 15, 2008 4:29 am as I find no need for the updated version with the 'by albums' function, since I really don't like to shuffle full albums.

There's one item I'd like to have fixed and one items I'd like to behave a bit differently. Like any media player Media Monkey plays a short moment of silence between two tracks, which makes the mix not sound like one fluent whole. I understand that this has to do with the PC loading the new track from my external hard drive to RAM memory, but I wonder if it is possible to make Media Monkey do this a bit better, so there is no silent moment. I guess it might improve if the music would be on my PC's hard drive, but since I'm using my work's laptop (Dell Latitude D830; XP prof 2000 SP 3; 1.97 GHz; 2 GB RAM) this is not allowed.

The second item is the priority your script gives to tracks that have not been played for six weeks. I think this bias has its use, but I would prefer Auto DJ to bias starred tracks as well. I use the star ratings in a particular way: Tracks that I really like get either 4.5 or 5 stars. I keep my list of 5 starred tracks limited to 700 MB, so I can burn my most most favorite songs to one mp3 CD, which I use in rental cars. My list of 4.5 AND 5 starred tracks are kept limited to about 5 GB for the 8 GB MicroSD card of my phone (the remaining 3 GB are for movies, pictures and other stuff), so my most favorite and most most favorite songs are on my phone. I'd like Auto DJ to give a, say, 1.02 bias to 5 starred tracks and a, say, 1.01 bias to 4.5 starred tracks; all other tracks would simply have a bias of 1.00. This would mean that on average every 100 tracks would contain 3 of my favorite songs, so I can here these a little more frequently than other songs.

Reading your script, I understand it generally since programming is a part of my job, but I don't speak the Visual Basic language yet, so I'm not able to program this myself. Is there anyone that is able to program this behavior?

Thanks, Eins
Post Reply