Skip to content

Commit

Permalink
Fix stopwatch not being properly started when the stream is started &…
Browse files Browse the repository at this point in the history
… setTime not working for certain streams

* Fix webaudio not properly calling into the stopwatch when started / stopped: Have no idea what I was thinking when I didn't do this, maybe just forgot or something. Was half a year ago so..

* Fixed setTime not working for some streams: Turns out dont_decode actually breaks a lot of stuff :l, either way there's a networking cooldown so it shouldn't be an issue.

There also seems to be problems with SetTime, but chances are it's a garrysmod issue. Hate how horrible bass streams are in gmod..
  • Loading branch information
Vurv78 committed Jan 16, 2022
1 parent 6b7d1f0 commit 5838556
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 46 deletions.
87 changes: 48 additions & 39 deletions lua/autorun/stopwatch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,25 @@

STOPWATCH_STOPPED, STOPWATCH_PLAYING, STOPWATCH_PAUSED = 0, 1, 2

local StopWatch = {}
StopWatch.__index = StopWatch
---@class Stopwatch
---@field playback_rate number
---@field playback_now number
---@field playback_elapsed number
---@field playback_duration number
---@field state number # STOPWATCH_STOPPED, STOPWATCH_PLAYING, STOPWATCH_PAUSED
---@field delay number
---@field looping boolean
local Stopwatch = {}
Stopwatch.__index = Stopwatch

local timer_now = RealTime

--- Creates a StopWatch.
-- @param number duration How long the stopwatch will last
-- @param function callback What to run when the stopwatch finishes.
local function Initialize(_, duration, fn)
local self = setmetatable({}, StopWatch)
---@param duration number # How long the stopwatch will last
---@param callback fun(self: Stopwatch) # What to run when the stopwatch finishes.
---@return Stopwatch
local function Initialize(_, duration, callback)
local self = setmetatable({}, Stopwatch)
self.playback_rate = 1
self.playback_now = timer_now()
self.playback_elapsed = 0
Expand All @@ -45,7 +54,7 @@ local function Initialize(_, duration, fn)
self.playback_elapsed = self.playback_duration
self.state = STOPWATCH_STOPPED
end
fn(self)
callback(self)
end)
timer.Stop(mangled)

Expand All @@ -54,20 +63,20 @@ local function Initialize(_, duration, fn)
return self
end

setmetatable(StopWatch, {
setmetatable(Stopwatch, {
__call = Initialize
})

--- Pauses a stopwatch at the current time to be resumed with :Play
function StopWatch:Pause()
function Stopwatch:Pause()
if self.state == STOPWATCH_PLAYING then
self.state = STOPWATCH_PAUSED
timer.Pause(self.timerid)
end
end

--- Resumes the stopwatch after it was paused. You can't :Play a :Stop(ped) timer, use :Start for that.
function StopWatch:Play()
function Stopwatch:Play()
if self.state == STOPWATCH_PAUSED then
self.playback_now = timer_now()
self.state = STOPWATCH_PLAYING
Expand All @@ -76,7 +85,7 @@ function StopWatch:Play()
end

--- Used internally by GetTime, don't use.
function StopWatch:UpdateTime()
function Stopwatch:UpdateTime()
if self.state == STOPWATCH_PLAYING then
local now = timer_now()
local elapsed = (now - self.playback_now) * self.playback_rate
Expand All @@ -88,7 +97,7 @@ end

--- Stops the timer with the stored elapsed time.
-- Continue from here with :Start()
function StopWatch:Stop()
function Stopwatch:Stop()
if self.state ~= STOPWATCH_STOPPED then
self:UpdateTime()
self.state = STOPWATCH_STOPPED
Expand All @@ -97,7 +106,7 @@ function StopWatch:Stop()
end

--- (Re)starts the stopwatch.
function StopWatch:Start()
function Stopwatch:Start()
if self.state == STOPWATCH_STOPPED then
self.playback_now = timer_now()
self.state = STOPWATCH_PLAYING
Expand All @@ -107,15 +116,15 @@ function StopWatch:Start()
end

--- Returns the playback duration of the stopwatch.
-- @return number Length
function StopWatch:GetDuration()
---@return number length
function Stopwatch:GetDuration()
return self.playback_duration
end

--- Returns the playback duration of the stopwatch.
-- @param number duration
-- @return StopWatch self
function StopWatch:SetDuration(duration)
---@param duration number
---@return Stopwatch self
function Stopwatch:SetDuration(duration)
self.playback_duration = duration
self.delay = duration
timer.Adjust( self.timerid, duration )
Expand All @@ -126,27 +135,27 @@ function StopWatch:SetDuration(duration)
end

--- Sets the playback rate / speed of the stopwatch. 2 is twice as fast, etc.
-- @param number n Speed
-- @return StopWatch self
function StopWatch:SetRate(n)
---@param speed number
---@return Stopwatch self
function Stopwatch:SetRate(speed)
self:UpdateTime()
self.playback_rate = n
self.playback_rate = speed
-- New Duration - Elapsed
self.delay = (self.playback_duration / n) - self.playback_elapsed
self.delay = (self.playback_duration / speed) - self.playback_elapsed
timer.Adjust( self.timerid, self.delay )
return self
end

--- Returns the playback rate of the stopwatch. Default 1
-- @return number Playback rate
function StopWatch:GetRate()
---@return number rate # Playback rate
function Stopwatch:GetRate()
return self.playback_rate
end

--- Sets the playback time of the stopwatch.
-- @param number n Time
-- @return StopWatch self
function StopWatch:SetTime(n)
---@param n number # Time
---@return Stopwatch self
function Stopwatch:SetTime(n)
self.playback_now = timer_now()
self.playback_elapsed = n
self.delay = (self.playback_duration - n) / self.playback_rate
Expand All @@ -156,22 +165,22 @@ function StopWatch:SetTime(n)
end

--- Returns the current playback time in seconds of the stopwatch
-- @return number Playback time
function StopWatch:GetTime()
---@return number time # Playback time
function Stopwatch:GetTime()
self:UpdateTime()
return self.playback_elapsed
end

--- Returns the current playback state of the stopwatch. 0 for STOPWATCH_STOPPED, 1 for STOPWATCH_PLAYING, 2 for STOPWATCH_PAUSED
-- @return number Playback state
function StopWatch:GetState()
---@return number state Playback state
function Stopwatch:GetState()
return self.state
end

--- Sets the stopwatch to loop. Won't call the callback if it is looping.
-- @param boolean loop Whether it's looping
-- @return StopWatch self
function StopWatch:SetLooping(loop)
---@param loop boolean Whether it's looping
---@return Stopwatch self
function Stopwatch:SetLooping(loop)
if self.looping ~= loop then
self.looping = loop
timer.Adjust( self.timerid, self.delay, 0, nil )
Expand All @@ -180,11 +189,11 @@ function StopWatch:SetLooping(loop)
end

--- Returns if the stopwatch is looping
-- @return boolean Looping
function StopWatch:GetLooping()
---@return boolean looping
function Stopwatch:GetLooping()
return self.looping
end

_G.StopWatch = StopWatch
_G.StopWatch = Stopwatch

return StopWatch
return Stopwatch
9 changes: 8 additions & 1 deletion lua/autorun/webaudio.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ end
]]

--- Initiate WebAudio struct for both realms
---@class WebAudio
---@field stopwatch Stopwatch
---@field radius number
---@field looping boolean
---@field parented boolean
---@field volume number # 0-1
_G.WebAudio = {}
WebAudio.__index = WebAudio

Expand Down Expand Up @@ -175,7 +181,7 @@ function WebAudio:Destroy(transmit)
return true
end

--- Returns time elapsed in URL stream.
--- Returns current time in URL stream.
-- Time elapsed is calculated on the server using playback rate and playback time.
-- Not perfect for the clients and there will be desync if you pause and unpause constantly.
-- @return number Elapsed time
Expand Down Expand Up @@ -378,6 +384,7 @@ local function createWebAudio(_, url, owner, bassobj, id)
self.bass = bassobj
self.parent_pos = Vector() -- Parent pos being nil means we will go directly to the parent's position w/o calculating local pos.
else
-- Stream will be set to 100 second length until the length of the audio stream is determined by the client.
self.stopwatch = StopWatch(100, function(watch)
if not watch:GetLooping() then
self:Pause()
Expand Down
20 changes: 16 additions & 4 deletions lua/webaudio/interface.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ function WebAudio:Play()

if self.playing == false then
self:AddModify(Modify.playing)

if self.stopwatch.state == STOPWATCH_STOPPED then
self.stopwatch:Start()
else
self.stopwatch:Play()
end

self.playing = true
self:Transmit()
return true
Expand All @@ -101,6 +108,7 @@ function WebAudio:Pause()

if self.playing then
self:AddModify(Modify.playing)
self.stopwatch:Pause()
self.playing = false
self:Transmit()

Expand Down Expand Up @@ -293,17 +301,21 @@ net.Receive("wa_info", function(len, ply)
-- Failed to create. Doesn't support 3d, or is block streamed.
stream:Destroy()
else
local length = net.ReadUInt(16)
local continuous = net.ReadBool()
local length = -2
if not continuous then
length = net.ReadUInt(16)
end

local file_name = net.ReadString()
stream.length = length
stream.filename = file_name
stream.needs_info = false

local watch = stream.stopwatch
watch:SetDuration(length)
watch:SetRate(stream.playback_rate)
watch:SetTime(stream.time)
watch:Start()
-- watch:SetRate(stream.playback_rate)
-- watch:SetTime(stream.time)
end
end
end)
Expand Down
8 changes: 6 additions & 2 deletions lua/webaudio/receiver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ net.Receive("wa_create", function(len)
net.Start("wa_info", true)
WebAudio.writeID(id)
net.WriteBool(false)
net.WriteUInt(self.length, 16)
local continuous = self.length < 0
net.WriteBool(continuous) -- If the stream is continuous, it should return something less than 0.
if not continuous then
net.WriteUInt(self.length, 16)
end
net.WriteString(self.filename)
net.SendToServer()
end
Expand Down Expand Up @@ -206,7 +210,7 @@ function updateObject(id, modify_enum, handle_bass, inside_net)
if hasModifyFlag(modify_enum, Modify.time) then
if inside_net then self.time = net.ReadUInt(16) end
if handle_bass then
bass:SetTime(self.time, true) -- 18 hours max, if you need more, wtf..
bass:SetTime(self.time) -- 18 hours max, if you need more, wtf..
end
end

Expand Down

0 comments on commit 5838556

Please sign in to comment.