Hi there. In my journey through running backing tracks on stage for a live band using GP5, I faced the fact that there is no “duration” concept for songs and setlists. This is because GP is probably not primarily designed for that. I searched here without any success, so I made my first GP Script and share it with you. Hope it helps, perhaps someone will make it better.
Basically : I decided to use the built-in “Artist” field of songs to store each song duration. So first, I entered every duration using the format mm:ss (eg. 05:43 = five minutes and forty three seconds).
Then : I added two Text Labels to my Global Rackspace, named lbl_Song_Duration and lbl_Setlist_Duration. I want the selected song duration to be displayed in the first one while the selected setlist complete duration is displayed in the second one.
And then I created this GLOBAL RACKSPACE script :
// Déclaration du widget textuel pour l'affichage
Var
lbl_Setlist_Duration, lbl_Song_Duration : Widget
setlistDurationAlreadyLoaded : Boolean
// Fonction utilitaire pour extraire la durée [MM:SS] du nom d'un morceau
Function ExtractDurationFromSongName(songName : String) Returns Integer
Var
posOpen, posColon, posClose : Integer
minStr, secStr : String
minutes, seconds : Integer
duration : Integer
duration = 0
posOpen = IndexOfSubstring(songName, "[", false)
posColon = IndexOfSubstring(songName, ":", false)
posClose = IndexOfSubstring(songName, "]", false)
// Si le format [MM:SS] est bien détecté dans le titre
If posOpen >= 0 And posColon > posOpen And posClose > posColon Then
minStr = CopySubstring(songName, posOpen + 1, posColon - posOpen - 1)
secStr = CopySubstring(songName, posColon + 1, posClose - posColon - 1)
minutes = StringToInt(minStr)
seconds = StringToInt(secStr)
// On retourne le total en secondes pour faciliter le calcul
duration = (minutes * 60) + seconds
End
result = duration // Retourne 0 si aucun format n'est trouvé
End
Function ExtractDurationFromString(durationString : String) Returns Integer
Var
duration, posColon, length : Integer
minStr, secStr : String
minutes, seconds : Integer
duration = 0
posColon = IndexOfSubstring(durationString, ":", false)
length = Length(durationString)
If posColon > -1 Then
minStr = CopySubstring(durationString, 0, posColon)
secStr = CopySubstring(durationString, posColon + 1, length)
minutes = StringToInt(minStr)
seconds = StringToInt(secStr)
// On retourne le total en secondes pour faciliter le calcul
duration = (minutes * 60) + seconds
End
result = duration
End
// Procédure principale qui calcule le temps total de la setlist active
function FormatSecondsToString(totalSeconds : Integer) Returns String
Var
hStr, mStr, sStr : String
displayText : String
finalHours, finalMinutes, finalSeconds : Integer
// Conversion du total des secondes en Minutes:Secondes pour l'affichage
finalHours = totalSeconds / 3600
finalMinutes = (totalSeconds % 3600) / 60
finalSeconds = totalSeconds % 60
// Formatage avec des zéros initiaux si nécessaire pour les minutes/secondes
If finalMinutes < 10 Then mStr = "0" + finalMinutes Else mStr = "" + finalMinutes End
If finalSeconds < 10 Then sStr = "0" + finalSeconds Else sStr = "" + finalSeconds End
hStr = "" + finalHours
// Construction de la chaîne d'affichage
If finalHours > 0 Then
displayText = hStr + ":" + mStr + ":" + sStr
Else
// Si moins d'une heure, on peut masquer le "0:" pour garder de la clarté
displayText = mStr + ":" + sStr
End
result = displayText
End
// Procédure principale qui calcule le temps total de la setlist active
function CalculateSetlistDuration()
Var
songCount : Integer
i : Integer
currentSongName : String
totalSeconds : Integer
totalSeconds = 0
songCount = GetSongCount() // Récupère le nombre total de morceaux de la setlist
// Boucle à travers tous les morceaux de la setlist active
For i = 0; i < songCount; i = i + 1 Do
currentSongName = GetSongName(i)
Print(currentSongName)
//totalSeconds = totalSeconds + ExtractDurationFromSongName(currentSongName)
totalSeconds = totalSeconds + ExtractDurationFromString(GetSongArtistName(i))
Print(totalSeconds)
End
// Mise à jour du widget sur votre écran
SetWidgetLabel(lbl_Setlist_Duration, FormatSecondsToString(totalSeconds))
End
// Called when the setlist changes - (GigScript/Global rackspace) only)
On SystemEvent Matching SetlistChanged
If GetCurrentSetlistIndex() > -1 Then
CalculateSetlistDuration() // Called when the setlist changes - (GigScript/Global rackspace) only)
End
End
// Called when you switch to another song
On Song(oldSongIndex : integer, newSongIndex : integer)
// A l'ouverture de GP5 même si opn est pas en mode setlist ce callback est appelé
// et dans ce cas cette fonction renvoie une ereur et bloque le script, on teste donc si on est en mode setlist
// en testant l'index de la setlist active
If GetCurrentSetlistIndex() > -1 Then
if !setlistDurationAlreadyLoaded Then
CalculateSetlistDuration()
setlistDurationAlreadyLoaded = true
End
SetWidgetLabel(lbl_Song_Duration, FormatSecondsToString(ExtractDurationFromString(GetSongArtistName(newSongIndex))))
End
End
I faced an issue, because GP5 is probabely loading songs even the setlist mode is not active, and unfortunately, calling Song functions will provoke a crash and further scripts will not run. This why there are tests like “GetCurrentSetlistIndex() > -1”
So the ideea is : each time the song selection changes, the duration of the song is displayed. Each time the setlist is changes, the total duration is displayed.