help with radio using sound.PlayURL

hey guys,

i have some code here (sort of lengthy) for a radio system using the bass module built into gmod. syntactically it is correct and it works kinda. i have a key bind set up to cycle through radio stations but here is the core.

but first, the problem. it works fine if the stream is active and it is broadcasting and all that. it plays, once playing it will stop when i stop it or change radio stations. BUT if i switch through them quickly, it will start all of these untraceable streams that i cant remove or stop. i tried making them start with no sound, but there is a few issues regarding that such as making a time (ie 5 seconds before it will actually start playing) but then if it takes more than 5 seconds to start broad casting and you change station it will start playing and you cant stop it. the are a few more issues but the main part is that i need it to work flawlessly.

i dont mind if stream/station A starts playing when station/stream B has been selected (and broadcasting) as long as i can find stream A and stop it.

[lua]
local radioEnts = {};
local streams = {};

local function playRadio(e)
local iStation = e.RadioStation;
e.RadioStation = nil;
local station = RadioStations[iStation][2];
sound.PlayURL(station, “3d mono noplay”, function(s)
if (!s || !s.IsValid || !s:IsValid()) then
print(“Unable to load radio station: " … station … " [” … iStation … “]”);
return;
end

	table.insert(streams, {iStation, e, s});
	
	if (!e.Radio) then
		e.Radio = {};
	end
	
	e.Radio.Channel = s;
	e.Radio.Channel:SetPos(e:GetPos());
	
	e.Radio.Station = iStation;
	
	table.insert(radioEnts, e);
end);

end

function _R.Entity:SetRadioStation(iStation)
self:StopRadioStation();
self.RadioStation = iStation;
self.RadioTime = CurTime() + 5;
end

function _R.Entity:StopRadioStation()
if (!istable(self.Radio) || !self.Radio.Channel) then
return;
end

table.RemoveByValue(radioEnts, self);
self.RadioStation = nil;
self.RadioTime = nil;
self.Radio.Channel:Stop();
self.Radio = nil;

end

hook.Add(“Think”, “RadioThink”, function()
for k,v in pairs(radioEnts) do
if (!IsValid(v) || !v.Radio) then
if (v.RadioTime) then
if (v.RadioTime <= CurTime()) then
playRadio(v);
else
continue;
end
else
table.remove(radioEnts, k);
continue;
end
end

	if (IsValid(v.Radio.Channel)) then
		if (v:IsVehicle() && LocalPlayer():GetVehicle() == v) then
			v.Radio.Channel:SetPos(LocalPlayer():EyePos());
		else
			v.Radio.Channel:SetPos(v:GetPos());
		end
		
		v.Radio.Channel:Play();
	end
end

// clean up ents (fake GC)
for k,v in pairs(streams) do
	if (IsValid(v[2]) || !v[2].Radio || v[2].Radio.Station != v[1]) then
		v[3]:Stop();
		table.remove(streams, k);
	end
end

end);

local RadioTime = 0;
local RadioText = “”;
net.Receive(“Radio”, function(l)
local ent = net.ReadEntity();
local bSet = tobool(net.ReadBit()) == true;
local station = net.ReadChar();

if (!IsValid(ent)) then
	return;
end

if (ent:IsVehicle() && LocalPlayer():InVehicle() && LocalPlayer():GetVehicle() == ent) then
	local str = "Off";
	
	if (bSet && station != 0) then
		str = RadioStations[station][1];
	end
	
	RadioTime = CurTime();
	RadioText = str;
end

if (!bSet || station == 0) then
	ent:StopRadioStation();
else
	ent:SetRadioStation(station);
end

end);

hook.Add(“HUDPaint”, “RadioPaint”, function()
if (RadioTime + 3 > CurTime() && RadioText != “”) then
draw.SimpleText(RadioText, “Treb24”, ScrW() / 2 + math.random(-5, 5), 15 * 3.5 + math.random(-5, 5), Color(100, 0, 0, 200), TEXT_ALIGN_CENTER);
draw.SimpleText(RadioText, “Treb24NoShadow”, ScrW() / 2, 15 * 3.5, Color(200, 0, 0, 200), TEXT_ALIGN_CENTER);
end
end);
[/lua]

any help regarding the issue or tidiness of the code is appreciated :slight_smile:

So, it doesn’t check if theres allready a valid radio station?

when you change the channel it stops the current one. but until the stream has started broadcasting it is invalid so you cant stop it. which means if you cycle through 3 stations quickly enough all 3 of them will start playing. and you will only be able to stop the last played station.

What about adding a delay then changing?

that MIGHT work but id be guessing a time for how long it takes for the stream to start broadcasting (like i said in the opening post)

if i have a 5 second delay and a stream takes 6 seconds to start broadcasting then the leak is there again.

[editline]14th March 2014[/editline]

i dont want to have to use the bass module (although perp uses it and it successfully doesnt have this problem)

Why not try to make it so if you change the radio station on the function for the next station make it so it sets the current radio time to 0 (RadioTime) so when it initializes it automatically ends straight away?

RadioTime and RadioText are only for displaying the current radio station selected.

I ran into this issue also with my radio. I went with having a flag that gets set when we’re waiting for a song to error or finish loading before we allow the user to do anything else. Just make sure you always keep track of the channel objects.

https://github.com/mcd1992/fgt_radio/blob/master/lua/autorun/fgt_radio.lua

if the build in module returned a channel straight away it would make it a lot easier and better in my opinion but oh well.

thanks heaps ill have a look and see if i cant fix it :slight_smile: