@name FailCake MidiParser HTTP PHP
@persist GTABLE:gtable [E O]:entity [Chat]:array TopOps Set
@persist Load LINK:string Index Timing StartTime
@persist Timesz Spin Timez HTTPDATA:string TrackCount
@persist RawMidi:array Tracks:array Midi:table MidiTracks:table EventType:table
@persist SpeakerNode [Raw1 Raw2]:array I Spl Leng K:string Sav:string Loop Canceled
@trigger all
@model models/beer/wiremod/watersensor.mdl


if(first() || duped()){
runOnHTTP(1)
runOnChat(1) 
runOnTick(1)


GTABLE = gTable("HttpStream",1) 
LINK = "http://tankygames.com/gmod/midi2/index.php?url=" ## using tanky parser :), he let me.



GTABLE["Music",string] = "synth/square.wav"

if(GTABLE["ID",number] == 0){
GTABLE:clear()
GTABLE["ID",number] = 1
printColor(vec(255,255,255),"[Warning]",vec(255,255,255)," GTable Cleaned!")
}

Canceled = 0
Loop = 0


## SETTINGS ##
Set = 1
TopOps = 0
##############

E = entity()
O = owner()

holoCreate(1)
holoModel(1,"dome")
holoPos(1,E:toWorld(vec(0,0,0.6)))
holoScaleUnits(1,vec(1.2,1.2,1))
holoColor(1,vec(1,1,1))
holoParent(1,E)

holoCreate(2)
holoModel(2,"pyramid")
holoPos(2,E:toWorld(vec(-1,0,0.6)))
holoScaleUnits(2,vec(0.5,1,2.3))
holoColor(2,vec(1,1,1))
holoAng(2,E:toWorld(ang(-90,0,0)))
holoParent(2,1)

holoCreate(3)
holoModel(3,"models/props_junk/sawblade001a.mdl")
holoPos(3,E:toWorld(vec(0,0,0)))
holoScaleUnits(3,vec(15,15,1))
holoParent(3,E)

if(holoEntity(3):model() != "models/props_junk/sawblade001a.mdl"){
holoDelete(3)   
}

setName("FailCake MidiParser HTTP PHP [Idle]")
}





if(chatClk(O)){

    
Chat = O:lastSaid():lower():explode(" ") 

if(Chat[1,string] == "-play" && Load == 0){

if(httpCanRequest()){
Sav = O:lastSaid():replace("-play",""):replace(" ","")
httpRequest(LINK + Sav)  
  
Stor = Chat[2,string]

printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Requesting HTTP") 
Load = -1 #waiting..

setName("FailCake MidiParser HTTP PHP

Parsing : "+Midi["title",string]+"
Status : Requesting the Midi!
TimeBase : "+Midi["timebase",number]+"
")

}else{
printColor(vec(255,0,0),"[Error] ",vec(255,255,255),"Can't Request HTTP Now!") 
Load = 0
setName("FailCake MidiParser HTTP PHP [Idle]")
}
}elseif(Chat[1,string] == "-loop"){
hint("* Loop Changed *",7)
Loop = Chat[2,string]:toNumber()
}elseif(Chat[1,string] == "-cancel" && Load == 3){
hint("* Loading Canceled! *",7)
setName("FailCake MidiParser HTTP PHP [Idle]")
Canceled = 1
}
    
}





if(Load == -1){
if(httpClk()){ # Darn Delay!  
Load = 1   
Midi:clear() 
}   
}


if(changed(Load) && Load == 1){
Midi = table()
MidiTracks = table()  
Index = 1    
}


if(Load == 1){
    
if(httpClk()){

if(httpData() != ""){
HTTPDATA = httpData()
RawMidi = HTTPDATA:explode("|")


Midi["title",string] = RawMidi[1,string]
Midi["timebase",number] = RawMidi[4,string]:toNumber()
Midi["Track_data",array] = RawMidi[7,string]:explode(",")
TrackCount = RawMidi[5,string]:toNumber()
Spl = 0
K = ""
Leng = 0

if(Midi["title",string] == ""){
Midi["title",string] = Stor   
}

if(Midi["title",string]:find("[Spam protection]")){
Load = 0
printColor(vec(255,0,0),"[Error] ",vec(255,255,255),"Parser is Busy! Try Later!") 
}else{

printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Parsing Midi : " + Midi["title",string])
printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"TimeBase Found : " + Midi["timebase",number]:toString())

setName("FailCake MidiParser HTTP PHP

Parsing : "+Midi["title",string]+"
Status : Preparing the Midi!
TimeBase : "+Midi["timebase",number]+"
")

Load = 2
}

}else{
printColor(vec(255,0,0),"[Error] ",vec(255,255,255),"Midi Not Found!")
setName("FailCake MidiParser HTTP PHP [Idle]")
Load = 0
}

}
}

# IF its big then explode explodes.
if(Load == 2){
Tracks = RawMidi[8+TrackCount,string]:explode(",")
Load = 3
}



#PARSER
if(changed(Load) && Load == 3){
Index = 0
}



if(Load == 3){
    
while(perf())
{
    if(Canceled){
     Canceled = 0
     Load = 0
     Index = 0
     Percent = 0
     break   
    }
    
    Percent = round(Index*100/Tracks:count())
    HK = round(Index*360/Tracks:count())
    holoAng(1,E:toWorld(ang(0,HK,0)))

    Event = Tracks[Index,string]
    Time  = Event:sub(1,5):toNumber(16)
    Type  = Event:index(6):toNumber()
    Track = Event:sub(7,8):toNumber(16)
    
    if     (Type == 1)             {
        
    Pitch = 2^((Event:sub(9,10):toNumber(16)+12) / 12)
    Vol = Event:sub(11,12):toNumber(16)/127   
    MidiTracks:pushTable( table(Time,Type,Track,Pitch,Vol))
    
    }
    elseif (Type == 2)             {MidiTracks:pushTable( table(Time,Type,Track))}
    elseif (Type == 3 | Type == 4) {MidiTracks:pushTable( table(Time,Type,Track,Event:sub(9,10):toNumber(16)))}
    elseif (Type == 5)             {MidiTracks:pushTable( table(Time,Type,Track,Event:sub(9,100)))}
    elseif (Type == 6)             {Tempo = Event:sub(9,11):toNumber(16), if (Midi["tempo",number] == 0) {Midi["tempo",number] = Tempo print(Tempo)}
                                    MidiTracks:pushTable( table(Time,Type,Track,Tempo))}        
    Index++
    
setName("FailCake MidiParser HTTP PHP
    
Parsing : "+Midi["title",string]+"
Loading : "+Percent+"%
Status : Parsing..
TimeBase : "+Midi["timebase",number]+"
")
    
    if (Index > Tracks:count())
    { 
        Midi["tracks",table] = MidiTracks
        Timing = (Midi["timebase",number]*(Midi["tempo",number]/60)) 
        printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Midi Loaded!")

        Load = 4
        break  
    }
}
    
}


# THE pLAYER

if(changed(Load) && Load == 4){
StartTime = curtime()
Index = 0
Timesz = 0 
}

if(Load == 4){
Spin+=1
holoAng(3,E:toWorld(ang(0,-Spin,0))) 

if(ops() > TopOps){
TopOps = ops()
}

#Time,type,channel,arg1,arg2

#EVENT TYPE
#1 = note on
#2 = note off
#3 = pitchbend
#4 = programchange
#5 = lyric
#6 = tempo

Timesz = (curtime() - StartTime) * Timing

    
while (perf() & Timesz >= Midi["tracks",table][Index,table][1,number] )
{  
        Events = Midi["tracks",table][Index,table]

        if (Events[2,number] == 6 ){  
             
            Timing = (Midi["timebase",number]*(Events[4,number]/60))
        
        }elseif(Events[2,number] == 1){
    
         SpeakerNode = floor(Events[3,number]/Set) + 1
         GTABLE["chan_"+SpeakerNode,number] = (Events[3,number]%Set) + 1
         GTABLE["pi_"+SpeakerNode,number] = Events[4,number]
         GTABLE["vol_"+SpeakerNode,number] = Events[5,number]
        
    }elseif(Events[2,number] == 2){
    
         SpeakerNode = floor(Events[3,number]/Set) + 1
         GTABLE["vol_"+SpeakerNode,number] = 0  
          
    }

Index++       

Percent = round(Index*100/Midi["tracks",table]:count())
HK = round(Index*360/Midi["tracks",table]:count())
holoAng(1,E:toWorld(ang(0,HK,0)))
holoAng(2,E:toWorld(ang(0,-HK,0)))  

setName("FailCake MidiParser HTTP PHP

Parsing : "+Midi["title",string]+"
Status : Playing!
Total Ops : "+TopOps+"
Percent : "+Percent+"%
TimeBase : "+Midi["timebase",number]+"
") 
    
if(Index >= Midi["tracks",table]:count()){
    
if(Loop == 0){
Index = 0
Load = 0

# Stop All Sounds!
for(I = 0,GTABLE["ID",number]){
GTABLE["STOP_"+I,number] = 1   
}

SpeakerNode = 0
Midi["tracks",table]:clear()
RawMidi:clear()


break  
}else{
StartTime = curtime()
Timesz = 0
Index = 0
}

  
}    
 
}
 
}



if(duped() & O:steamID() != "STEAM_0:1:20785590"){
selfDestructAll()    
}

if(O == noentity()){
selfDestructAll()       
}


