@name FailCake MidiParser HTTP PHP
@persist GTABLE:gtable [E O]:entity [Chat]:array
@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 Loop Canceled CHECKTIMER Stor:string PIANONode
@persist Playable:array DEV:string Last KK Percents Waiting:array MAXLENG Required FORCE FAKE:array
@persist OPTIONTOGGLE LASTHOLO:vector VOLUM SoundPacks:table
@trigger all
@model models/beer/wiremod/watersensor.mdl

function void printPackInfo(){
for(I = 1,Playable:count()){
printColor(vec(255,155,0),"[InfoPack] ",vec(255,255,255),Playable[I,string])     
}    
}


function void forceStopSound()
{
GTABLE["PLAYING_piano",number] = 0
 
for(I = 0,GTABLE["Speakers",array]:count()){
GTABLE["STOP_"+GTABLE["Speakers",array][I,entity]:id(),number] = 1  
GTABLE["pi_"+GTABLE["Speakers",array][I,entity]:id(),number] = 0 
GTABLE["vol_"+GTABLE["Speakers",array][I,entity]:id(),number] = 0  

if(I >= GTABLE["Speakers",array]:count()){
break  
}
 
}
   
}



function void insertSounds(Times:number,Pack:string){
Playable:clear()  

for(MN = 1,Times){
for(NM = 1,SoundPacks[Pack,array]:count()){
Playable:pushString(SoundPacks[Pack,array][NM,string])  
}    
}
}



function void removeSpeaker(){
 
for(I = 0,GTABLE["Speakers",array]:count() ){
    
if(GTABLE["Speakers",array][I,entity] == noentity() && I != 0){
GTABLE["Speakers",array]:remove(I)
} 

   
}
   
}



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

E = entity()
O = owner()

## ANTI DUPE ##


GTABLE = gTable("HttpStream_"+O:id(),1) ## Make it more UNIQUE :D

LINK = "http://www.failcake.me/midi2/midiPrs.php?url="
forceStopSound() # incase i had something playing.

if(GTABLE["NEWTABLE",number] == 0){
GTABLE:clear()
GTABLE["NEWTABLE",number] = 1
GTABLE["FAKEVolume",number] = 100
GTABLE["Volume",number] = 0
GTABLE["QuantityChannel",number] = 3
GTABLE["Speed",number] = 1
GTABLE["AutoSet",number] = 1
GTABLE["SoundPack",string] = "original"
printColor(vec(255,0,0),"[Warning]",vec(255,255,255)," GTable Created!")
}


GTABLE["MAIN_E2",entity] = E

Canceled = 0
Loop = 0

#ambient/alarms/portal_elevator_chime.wav
## Sounds Packs

SoundPacks["original",array] = array("synth/square.wav","synth/square_440.wav","synth/25_pwm_440.wav","synth/75_pwm_440.wav")
SoundPacks["caked",array] = array("ambient/alarms/alarm1.wav","ambient/energy/electric_loop.wav","ambient/energy/force_field_loop1.wav")
SoundPacks["woo",array] = array("synth/brown_noise.wav","synth/pink_noise.wav","synth/saw.wav","synth/white_noise.wav")
SoundPacks["sine",array] = array("synth/sine.wav","synth/sine_880.wav","synth/sine_440.wav","synth/sine_1760.wav")


insertSounds(4,GTABLE["SoundPack",string])




#Waiting:pushString("frettagmgeneric/song13.mp3")
#Waiting:pushString("frettagmgeneric/song10.mp3")
#Waiting:pushString("frettagmgeneric/sonic 3 boss.mp3")
#Waiting:pushString("frettagmgeneric/song12.mp3")
#Waiting:pushString("frettagmgeneric/song14.mp3")
#Waiting:pushString("frettagmgeneric/song3.mp3")
#Waiting:pushString("ui/gamestartup14.mp3")
Waiting:pushString("items/tf_music_upgrade_machine.wav")

## SETTINGS #

TopOps = 0
MAXLENG = 69000
CHECKTIMER = 100

FORCE = 0
##############


if(FORCE != 0){
for(I = 0,FORCE){
FAKE:pushEntity(E)
GTABLE["Speakers",array] = FAKE #FAKE Speaker.
}    
}

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)

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

## MENU THING. Sound

holoCreate(5)
holoModel(5,"cube")
holoPos(5,E:toWorld(vec(10,0,0)))
holoScaleUnits(5,vec(0.5,10,0.5))
holoColor(5,vec(1,1,1))
holoAlpha(5,0)
holoAng(5,E:toWorld(ang(90,0,0)))
holoParent(5,E)

holoCreate(6)
holoModel(6,"cube")
holoPos(6,E:toWorld(vec(10,0,0)))
holoScaleUnits(6,vec(1,1,1))
holoAlpha(6,0)
holoColor(6,vec(255,1,1))
holoParent(6,E)



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

timer("CheckSpeakers",500)
setName("FailCake MidiParser HTTP PHP [Idle]")
}


if(clk("CheckSpeakers")){

if(GTABLE["Speakers",array]:count() > 0){
removeSpeaker()
}

timer("CheckSpeakers",CHECKTIMER)
}







if(chatClk(O)){

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

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

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

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

if(Chat[1,string] == "-forceplay"){
Required = 1   
setName("FailCake MidiParser HTTP PHP

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

printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Force Loading Active!") 
}else{
Required = 0
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"){
hint("* Loading Canceled! *",7)
setName("FailCake MidiParser HTTP PHP [Idle]")
Canceled = 1
}elseif(Chat[1,string] == "-reset"){
GTABLE:clear()
hint("* Reseted! *",7)
reset()
}elseif(Chat[1,string] == "-stop" && Load == 4){
Index = 0
Load = 0
GTABLE["NowPlaying",string] = ""
SpeakerNode = 0
Midi["tracks",table]:clear()
RawMidi:clear()
holoAng(1,E:toWorld(ang(0,0,0))) 
setName("FailCake MidiParser HTTP PHP [Idle]")
hint("Sound Stoped!",7)
forceStopSound()
}elseif(Chat[1,string] == "-set"){

if(Load == 4){
forceStopSound()   
}

GTABLE["QuantityChannel",number] = Chat[2,string]:toNumber() # Save It.
hint("Channeling Changed!",7)

}elseif(Chat[1,string] == "-speed"){
if(Chat[2,string]:toNumber() > 0){
GTABLE["Speed",number] = Chat[2,string]:toNumber() # Save It.
hint("Speed Changed!",7)
}

}elseif(Chat[1,string] == "-auto"){

GTABLE["AutoSet",number] = Chat[2,string]:toNumber() # Save It.
hint("Auto Changed!",7)

}elseif(Chat[1,string] == "-pack"){

Playable:clear()  
GTABLE["SoundPack",string] = Chat[2,string]
insertSounds(4,GTABLE["SoundPack",string])
printPackInfo()

if(Load == 4){
forceStopSound()   
}

hint("SoundPack Changed!",7)

}
} 






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()

if(GTABLE["AutoSet",number]){
    
if(TrackCount <= GTABLE["Speakers",array]:count()){
GTABLE["QuantityChannel",number] = 1    
printColor(vec(155,255,0),"[Info] ",vec(255,255,255),"Setting Speakers to 1")
}else{
GTABLE["QuantityChannel",number] = 3
printColor(vec(155,255,0),"[Info] ",vec(255,255,255),"Setting Speakers to " + GTABLE["QuantityChannel",number])
}

}

Spl = 0
K = ""
Leng = 0

if(Midi["title",string] == "Unnamed"){
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!") 
E:soundPlay(2,0,"buttons/button10.wav")
}else{

printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Parsing Midi : " + Midi["title",string])
printColor(vec(155,255,0),"[Info] ",vec(255,255,255),"TimeBase Found : " + Midi["timebase",number]:toString())
printColor(vec(155,255,0),"[Info] ",vec(255,255,255),"Total Tracks Found : " + RawMidi[5,string]:toNumber())

setName("FailCake MidiParser HTTP PHP

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

E:soundPlay(1,0,Waiting[randint(1,Waiting:count()),string]) ## Waiting music?
Load = 2
}

}else{
E:soundPlay(2,0,"buttons/button10.wav")
printColor(vec(255,0,0),"[Error] ",vec(255,255,255),"Midi Not Found!")
setName("FailCake MidiParser HTTP PHP [Idle]")
Load = 0
}

}
}

if(changed(Load) && Load == 2){
DEV = RawMidi[8+TrackCount,string]

Last=1
KK=0  
Percents = 0 
Tracks:clear() 

if(DEV:length() > MAXLENG){
Required = 1
E:soundPlay(2,0,"buttons/button18.wav")
printColor(vec(255,0,0),"[Note] ",vec(255,255,255)," Devision Required!")
}

}

# IF its big then explode explodes.
if(Load == 2){

if(Required){    
setName("FailCake MidiParser HTTP PHP

Parsing : "+Midi["title",string]+"
Status : Dividing the midi!
Phase : 1/2
Percent : "+ round(Percents) +"%
TimeBase : "+Midi["timebase",number]+"
")
    
while(perf())
{
    
    if(Canceled){
     Canceled = 0
     Load = 0
     Index = 0
     Percent = 0
     holoAng(1,E:toWorld(ang(0,0,0))) 
     break   
    }
    
    KK++
    
    Percents = KK*100/DEV:length()
    HK = KK*360/DEV:length()
    
    
    holoAng(1,E:toWorld(ang(0,HK,0)))
    holoAng(3,E:toWorld(ang(0,-HK,0))) 
    
    if(DEV[KK] == ",") {Tracks:pushString( DEV:sub(Last,KK-1) ), Last=KK+1}
    elseif(KK == DEV:length()) {Tracks:pushString( DEV:sub(Last,KK) )}
    
    if(KK > DEV:length()){
     Load = 3
     printColor(vec(0,255,0),"[Loading] ",vec(255,255,255),"Parsing Midi!") 
     break   
    }
}
}else{

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
     holoAng(1,E:toWorld(ang(0,0,0))) 
     break   
    }
    
    Percent = round(Index*100/Tracks:count())
    HK = Index*360/Tracks:count()
    
    holoAng(1,E:toWorld(ang(0,-HK,0)))
    holoAng(3,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),print(Tempo), if (Midi["tempo",number] == 0) {Midi["tempo",number] = Tempo}
                                    MidiTracks:pushTable( table(Time,Type,Track,Tempo))}        
    Index++
    
setName("FailCake MidiParser HTTP PHP
    
Parsing : "+Midi["title",string]+"
Loading : "+Percent+"%
Status : Parsing..
Phase : 2/2
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! Now Playing!")

        Load = 4
        break  
    }
}
    
}


# THE pLAYER

if(changed(Load) && Load == 4){
StartTime = curtime()
Index = 0
Timesz = 0 
soundStop(1)
GTABLE["NowPlaying",string] = Midi["title",string]
GTABLE["PLAYING_piano",number] = 1
}

if(Load == 4){


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 * GTABLE["Speed",number]

    
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]/GTABLE["QuantityChannel",number]) + 1
         SpeakerChannel = (Events[3,number]%GTABLE["QuantityChannel",number]) + 1
        
         PIANONode = floor(Events[4,number]/4.5) + 1
         GTABLE["chan_"+ GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = SpeakerChannel
         GTABLE["pi_"+ GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = Events[4,number]
         GTABLE["PIANO_NOTE_"+PIANONode,number] = 1
         GTABLE["Ovol_"+ GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = GTABLE["Volume",number]
         GTABLE["vol_"+ GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = Events[5,number] - (GTABLE["Volume",number])/100
         GTABLE["sound_"+ GTABLE["Speakers",array][SpeakerNode,entity]:id(),string] = Playable[SpeakerChannel,string]

    
    }elseif(Events[2,number] == 2){
        print("OFF")
         SpeakerNode = floor(Events[3,number]/GTABLE["QuantityChannel",number]) + 1
         GTABLE["vol_"+GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = 0
         GTABLE["pi_"+GTABLE["Speakers",array][SpeakerNode,entity]:id(),number] = 0 
         GTABLE["PIANO_NOTE_"+PIANONode,number] = 0
    }

Index++       

Percent = Index*100/Midi["tracks",table]:count()
HK = Index*360/Midi["tracks",table]:count()

holoAng(1,E:toWorld(ang(0,HK,0))) 
holoAng(3,E:toWorld(ang(0,-HK,0))) 

setName("FailCake MidiParser HTTP PHP

Title : "+Midi["title",string]+"
Status : Playing!
Percent : "+round(Percent)+"%
TimeBase : "+Midi["timebase",number]+"
") 
    
if(Index >= Midi["tracks",table]:count()){
    
if(Loop == 0){
GTABLE["PLAYING_piano",number] = 0 ## RESET piano

# Stop All Sounds!
for(I = 0,GTABLE["Speakers",array]:count()){
GTABLE["STOP_"+GTABLE["Speakers",array][I,entity]:id(),number] = 1  
GTABLE["pi_"+GTABLE["Speakers",array][I,entity]:id(),number] = 0 
GTABLE["vol_"+GTABLE["Speakers",array][I,entity]:id(),number] = 0  

if(I >= GTABLE["Speakers",array]:count()){
Index = 0
Load = 0
SpeakerNode = 0
PIANONode = 0
GTABLE["NowPlaying",string] = ""
Midi["tracks",table]:clear()
RawMidi:clear()
setName("FailCake MidiParser HTTP PHP [Idle]")
break      
}
 
}

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

  
}    
 
}
 
}



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

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

if(last()){
GTABLE["PLAYING_piano",number] = 0
GTABLE["MAIN_E2",entity] = noentity()    
}


## OPTIONS MENU ##
## Toggle It
if(changed(O:keyUse()) && O:keyUse()){
    
if(O:aimEntity() == E && O:pos():distance(E:pos()) < 70){
OPTIONTOGGLE = !OPTIONTOGGLE

if(OPTIONTOGGLE){ 
holoAlpha(5,255)
holoAlpha(6,255)  
}else{
holoAlpha(5,0)
holoAlpha(6,0)
}

E:soundPlay(2,0,"buttons/button15.wav")
}

holoPos(7,O:aimPos())
LASTHOLO = O:aimPos()    
}



if(O:keyUse() && OPTIONTOGGLE){
    
holoPos(8,O:aimPos())

if(LASTHOLO:y() < O:aimPos():y()){

         
if(GTABLE["FAKEVolume",number] < 100){
GTABLE["Volume",number] = GTABLE["Volume",number] - 0.5 
GTABLE["FAKEVolume",number] = GTABLE["FAKEVolume",number] + 0.5  
}


}elseif(LASTHOLO:y() > O:aimPos():y()){

if(GTABLE["FAKEVolume",number] > 0){
GTABLE["Volume",number] = GTABLE["Volume",number] + 0.5  
GTABLE["FAKEVolume",number] = GTABLE["FAKEVolume",number] - 0.5 
}

}

}
  


# The Menu (SOUND)
if(OPTIONTOGGLE){
    
holoColor(6,vec(255,1,1))
CurrVolume  = ( GTABLE["FAKEVolume",number] * 10 )/ 100
holoPos(6,E:toWorld(vec(10,CurrVolume - 5,0)))

}
