library Muscii import SoundControl public struct Note string path integer volume real pitch Note previous Note next method copy takes nothing returns Note return Note.create(this.path,this.volume,this.pitch) end method play takes nothing returns nothing SoundControl.play(this.path,this.pitch,this.volume) end static method create takes string path, integer volume, real pitch returns Note Note t = new Note() t.path = path t.volume = volume t.pitch = pitch t.previous = null t.next = null return t end end public struct Chord Note first Note last Chord previous Chord next method copy takes nothing returns Chord Note iterator = this.first Chord new = Chord.create(iterator) loop iterator = iterator.next exitwhen iterator == null new.addNote(iterator) end return new end method play takes nothing returns nothing Note iterator = this.first loop exitwhen iterator == null iterator.play() iterator = iterator.next end end method addNote takes Note n returns Chord Note copy = n.copy() Note temp = this.last temp.next = copy copy.previous = temp return this end static method create takes Note n returns Chord Note q = Note.create(n.path,n.volume,n.pitch) Chord c = new Chord() c.previous = null c.next = null c.first = q c.last = q return c end end public struct Muscii private static Muscii array db private static integer dbIndex = -1 Chord first Chord last Chord iterator real tempo //in whole notes per minute timer clock integer count integer queueCount MyCallBackFunc cbf Muscii queued static method interrupt takes nothing returns nothing integer index = 0 Muscii temp loop exitwhen index>dbIndex temp = db[index] PauseTimer(temp.clock) index = index + 1 end end method callback takes MyCallBackFunc func returns Muscii this.cbf = func return this end method copy takes nothing returns Muscii Chord iterator = this.first Muscii new = Muscii.create(iterator,this.tempo) loop iterator = iterator.next exitwhen iterator == null new.addChord(iterator.copy()) end return new end method play takes nothing returns Muscii playCounted(-1) return this // for chaining end method playCounted takes integer count returns Muscii this.count = count TimerStart(this.clock,1. / (this.tempo / 60.),true, function p) return this end method enqueue takes Muscii next, integer queueCount returns Muscii // if the target Muscii is already queuing something, it is in use - we // therefore copy it. if next.queued == null then this.queued = next else this.queued = next.copy() end this.queueCount = queueCount return this.queued end method stop takes nothing returns Muscii PauseTimer(this.clock) this.iterator = this.first return this end method addChord takes Chord c returns Muscii Chord q = this.last Chord copy = c.copy() q.next = copy this.last = copy copy.previous = q return this end static method create takes Chord c, real tempo returns Muscii Muscii m = new Muscii() Chord cop = c.copy() m.first = cop m.last = cop m.iterator = cop m.tempo = tempo m.clock = CreateTimer() m.queued = null m.cbf = null m.clock.setData(m castTo int) dbIndex = dbIndex + 1 db[dbIndex] = m return m end private static method p takes nothing returns nothing Muscii m = GetExpiredTimer().getData() castTo Muscii Muscii next Chord now = m.iterator now.play() if now.next != null then m.iterator = now.next else m.iterator = m.first if m.count>-1 then m.count=m.count-1 if m.count==-1 then m.stop() next = m.queued if next != null then next.playCounted(m.queueCount) end m.queued = null if m.cbf != null then m.cbf.doCallback() m.cbf = null end end end end end end interface MyCallBackFunc function doCallback() returns nothing end end // usage example //init // Muscii m = new Muscii() // m.callback(() -> print("hello")) //end endlibrary