Music System with requests skipping to the last song

I have been stumped on this for a while and cannot figure this out. I have followed other dev forum tutorials and for some reason mine does not add up correctly. I am unable to test the queue as it keeps skipping through to the last song. Any suggestions as to how to fix this? I’m trying to get it to play one at a time.

while wait() do
    if Music.IsPlaying == false then
        local SelectedSong
        Music.TimePosition = 0
        if not Queue[1] then
            for Order = 1, #Songs do
                SelectedSong = "rbxassetid://"..Songs[Order]
                local Success, SongInfo = pcall(function()
                    return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
                end)
                SongName.Value = SongInfo.Name
                RequestedBy.Value = "Server"
                Music.SoundId = SelectedSong
            end
        elseif Queue[1] then
            SelectedSong = "rbxassetid://"..Queue[1].SongID
            local Success, SongInfo = pcall(function()
                return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
            end)
            SongName.Value = SongInfo.Name
            RequestedBy.Value = Queue[1].PlayerName
            table.remove(Queue, 1)
        end
        Music:Play()
        wait(Music.TimeLength)
    end
end
1 Like

I believe your main issue is in this for loop:

for Order = 1, #Songs do
    SelectedSong = "rbxassetid://"..Songs[Order]
    local Success, SongInfo = pcall(function()
        return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
    end)
    SongName.Value = SongInfo.Name
    RequestedBy.Value = "Server"
    Music.SoundId = SelectedSong
end

Although your code was a bit confusing and I’m not sure I fully understand the entire thing, I can see in this particular for loop, you never add a break at any point.

The code does fill in SelectedSong as the first song, but since the loop doesn’t stop, it then moves onto the second song and replaces SelectedSong with that, and then does the same for the third, and so on until it reaches the end of the array and replaces SelectedSong with the last item.

If that information doesn’t fully fix your problem, what exactly are you trying to do in this piece of code? I can tell you’re meaning to switch to this when the queue is empty, but what is it for? Are you trying to fall back to a second queue when the main one is empty? Are you trying to add another song to the queue? Or are you doing something else that I can’t figure out? I can’t offer an exact solution because I’m not confident I entirely know what your music system is supposed to be doing in the first place.

Thank you for getting back to me with my issue. So I should just need to add ‘break’ after Music.SoundId?
Edit:
I added it, now it just loops the same song (The first song.)

That didn’t fix it because now it only uses the first one in the list and then stops the loop.

Sorry, but can you just explain to me what this bit of code is meant to do? I can’t help you more until I know what it’s for.

for Order = 1, #Songs do
    SelectedSong = "rbxassetid://"..Songs[Order]
    local Success, SongInfo = pcall(function()
        return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
    end)
    SongName.Value = SongInfo.Name
    RequestedBy.Value = "Server"
    Music.SoundId = SelectedSong
end

It has a playlist which has some id’s and it’s supposed to play them in order, then when someone queues a song, it plays it after that song has finished, then after the queued song is finished, it goes back to the queue.
Edit: Full code:
Edit 2: Removed full code.

1 Like

Gotcha, so Songs and Queue are both queues, but Queue is filled with songs requested by players and Songs is the default queue when all player requested songs have finished playing.

In that case, you don’t need to loop through the entirety of Songs, you just need a variable to keep track of what position/index the script is at in the Songs queue.

local songIndex = 1 --Start at the first song
while wait() do
	if Music.IsPlaying == false then
		local SelectedSong
		Music.TimePosition = 0
		if not Queue[1] then
			--Use songIndex to find song
			SelectedSong = "rbxassetid://"..Songs[songIndex]
			
			local Success, SongInfo = pcall(function()
				return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
			end)
			SongName.Value = SongInfo.Name
			RequestedBy.Value = "Server"
			Music.SoundId = SelectedSong

			--Go to the next song afterwards
			songIndex = songIndex+1

			--If song exceeds length of table, loop back around to 1
			if songIndex > #songs then
				songIndex = 1
			end
		elseif Queue[1] then
			SelectedSong = "rbxassetid://"..Queue[1].SongID
			local Success, SongInfo = pcall(function()
				return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
			end)
			SongName.Value = SongInfo.Name
			RequestedBy.Value = Queue[1].PlayerName
			table.remove(Queue, 1)
		end
		Music:Play()
		wait(Music.TimeLength)
	end
end

Tell me if that works for you or if anything is unclear.

I’ll test it now, thank you for the support btw! :slight_smile:
Edit: With the queue, it recognises the ID but does not change to it. I think it’s because it didnt change the SoundId, i’m retesting.
Edit 2: Works perfectly, tysm. <3

1 Like

No problem, I’m happy to help.

And, although this isn’t part of your issue, here’s an additional tip: These are intended to be essentially the same code, correct?

local Success, SongInfo = pcall(function()
	return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
end)
SongName.Value = SongInfo.Name
RequestedBy.Value = "Server"
Music.SoundId = SelectedSong
local Success, SongInfo = pcall(function()
	return MarketPlaceService:GetProductInfo(string.sub(SelectedSong, 14), Enum.InfoType.Asset)
end)
SongName.Value = SongInfo.Name
RequestedBy.Value = Queue[1].PlayerName

Instead of retyping the same thing twice, you can make this into a function and call it whenever you need that bit of code, only having to change up the arguments to fit the situation.

function LoadSong(SoundID, RequestedBy)
	RequestedBy = RequestedBy or "Server" --Makes RequestedBy default to "Server"
	
	local Success, SongInfo = pcall(function()
		return MarketPlaceService:GetProductInfo(SoundID, Enum.InfoType.Asset)
	end)
	SongName.Value = SongInfo.Name
	RequestedBy.Value = "Server"
	Music.SoundId = "rbxassetid://"..SoundID
end

Usage example:

LoadSong(1842940253, "John Doe")
--This should load the Roblox song "Snapped" and specify it was requested by John Doe

This is a part of the don’t repeat yourself (DRY) principle in coding. In summary, if you’re typing the same chunk of code twice, you should see if there’s a way to change it so it only has to be typed once. Because usually, there is a way.

1 Like