quraji
zap
- Reaction score
- 144
MusicTracks by quraji
The latest in my slew of extremely useful submissions.Humor aside, you might actually use this one
Nah, just kidding.
What is it?
This is a struct designed to simulate a 'musictrack' type. Create em' and play em'. More info in the code
Why?
Because.
Picture?
Not this time.
Code?
Right-o!
Change Log
Demo map?
Aye, have that too!
The latest in my slew of extremely useful submissions.Humor aside, you might actually use this one
Nah, just kidding.
What is it?
This is a struct designed to simulate a 'musictrack' type. Create em' and play em'. More info in the code
Why?
Because.
Picture?
Not this time.
Code?
Right-o!
JASS:
library MusicTracks
/* by quraji v1.02
About:
This library introduces the musictrack struct. The purpose of the
musictrack struct is to abstract a 'music' type, since there isnt
one in Wc3. It also extends the functionality, offering easy
pausing/resuming/playing of the track.
Usage:
Just copy this library into your map, then create musictrack structs
as you would any other. Then use the provided methods to control them.
One extra functionality is that you may specify a function to run when
a particular track ends (if it doesnt loop).
Definitions:
Members:
string path - This is the path of the music/sound file
player porPlayer - This is the player for which the music will play
boolean looping - If true, the track will loop
Methods:
method pause - This will pause the track
method resume - This will play the track from the paused position
method stop - This will stop a track (dead in its tracks...har har?)
method play - This will play the track from the beginning
method operator position= - This will set the track play position
and will play from that position (if it was playing already)
Ex:
local musictrack mt = mt.create("path", Player(0))
set mt.Play()
set mt.Position=5000 // will jump to 5 seconds
method operator position - Returns the play position of the track
method operator onEnd= - This sets the function to run when the track ends (see notes)
Notes:
Some extra notes on the usages of OnEnd=. This method allows you to run
a function whenever the track ends (and isnt looping). This will allow you
to do some useful things. For example, you have an array of musictracks and
want the next track in the sequence to play automatically, you can do that.
It must follow this interface:
function interface trackendfunc takes nothing returns nothing
Think of it as an event response to a musictrack ending. Within that function
you may use EndingMusicTrack or GetEndingMusicTrack() to retrieve the musictrack.
*/
globals
// this is how often the track positions will be updated
// you don't want anything more than .1
// smaller is better here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin :D" loading="lazy" data-shortname=":D" />
private constant real UPDATE_PERIOD = .01
endglobals
function interface trackendfunc takes nothing returns nothing
globals
musictrack EndingMusicTrack
endglobals
function GetEndingMusicTrack takes nothing returns musictrack
return EndingMusicTrack
endfunction
globals
private musictrack array TracksToUpdate
private integer Update_Top = 0
endglobals
struct musictrack
// track info (user accessible)
string path
player forPlayer
boolean looping = false
// internal track stuff
private trackendfunc onend
private integer pos = 0
private integer duration
private boolean allowPause = false
private boolean allowResume = false
private boolean active = false
private boolean remove = false
////////////////////
// PRIVATE METHODS
private method onDestroy takes nothing returns nothing
set .remove = true
if (GetLocalPlayer()==.forPlayer) then
call StopMusic(false)
endif
endmethod
private method add takes nothing returns nothing
set TracksToUpdate[Update_Top] = this
set Update_Top = Update_Top+1
endmethod
private method update takes nothing returns boolean
if (.remove==true) then
set .remove = false
return true
endif
set .pos = .pos+R2I(UPDATE_PERIOD*1000)
if (.pos>=.duration) then
if (.looping==true) then
call .play()
else
set .allowPause = false
set .active = false
if (GetLocalPlayer()==.forPlayer) then
call StopMusic(false)
endif
if (.onend!=0) then
set EndingMusicTrack = this
call .onend.execute()
endif
return true
endif
endif
return false
endmethod
private static method updater takes nothing returns nothing
local musictrack mt
local integer i = 0
loop
exitwhen (i>=Update_Top)
set mt = TracksToUpdate<i>
if (mt.update()!=false) then
set TracksToUpdate<i> = TracksToUpdate[Update_Top-1]
set Update_Top = Update_Top-1
else
set i = i+1
endif
endloop
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), UPDATE_PERIOD, true, function musictrack.updater)
endmethod
/////////////////
// USER METHODS
// pauses the track
method pause takes nothing returns nothing
if (.allowPause==true) then
set .allowResume = true
set .allowPause = false
if (GetLocalPlayer()==.forPlayer) then
call StopMusic(false)
endif
set .remove = true
endif
endmethod
// resumes the track after a pause
method resume takes nothing returns nothing
if (.allowResume==true) then
set .allowResume = false
set .allowPause = true
if (GetLocalPlayer()==.forPlayer) then
call PlayMusicEx(.path, .pos, 0)
endif
call .add()
endif
endmethod
// stop a track
method stop takes nothing returns nothing
if (GetLocalPlayer()==.forPlayer) then
call StopMusic(false)
endif
set .allowPause = false
set .allowResume = false
set .active = false
set .remove = true
endmethod
// plays track from beginning
method play takes nothing returns nothing
if (GetLocalPlayer()==.forPlayer) then
call StopMusic(false)
call PlayMusicEx(.path, 0, 0)
endif
set .allowPause = true
set .allowResume = false
set .pos = 0
if (.active==false) then
call .add()
set .active = true
endif
endmethod
method operator position= takes integer i returns nothing
call .pause()
if (i<0) then
set .pos = 0
else
set .pos = i
endif
call .resume()
endmethod
method operator position takes nothing returns integer
return .pos
endmethod
method operator onEnd= takes trackendfunc f returns nothing
set .onend = f
endmethod
static method create takes string path, player forPlayer returns musictrack
local musictrack t = musictrack.allocate()
set t.path = path
set t.forPlayer = forPlayer
set t.duration = GetSoundFileDuration(path)
return t
endmethod
endstruct
////////////////////////
// WC3 format functions, if you like them better
function SetMusicTrackPath takes musictrack mt, string path returns nothing
set mt.path = path
endfunction
function SetMusicTrackPlayer takes musictrack mt, player p returns nothing
set mt.forPlayer = p
endfunction
function IsMusicTrackLooping takes musictrack mt returns boolean
return mt.looping
endfunction
function LoopMusicTrack takes musictrack mt, boolean flag returns nothing
set mt.looping = flag
endfunction
function PauseMusicTrack takes musictrack mt returns nothing
call mt.pause()
endfunction
function ResumeMusicTrack takes musictrack mt returns nothing
call mt.resume()
endfunction
function StopMusicTrack takes musictrack mt returns nothing
call mt.stop()
endfunction
function PlayMusicTrack takes musictrack mt returns nothing
call mt.play()
endfunction
function SetMusicTrackPlayPosition takes musictrack mt, integer p returns nothing
set mt.position = p
endfunction
function CreateMusicTrack takes string path, player forPlayer returns musictrack
return musictrack.create(path, forPlayer)
endfunction
endlibrary
</i></i>
Change Log
v1.02
Fixed a bug which caused the onEnd function to not execute.
Fixed an omission which caused GetEndingMusicTrack() to return nothing.
v1.01
Tweaked some very minor things.
Changed method naming convention, to a first letter is lowercase style, as is most common.
Fixed a bug which caused the onEnd function to not execute.
Fixed an omission which caused GetEndingMusicTrack() to return nothing.
v1.01
Tweaked some very minor things.
Changed method naming convention, to a first letter is lowercase style, as is most common.
Demo map?
Aye, have that too!