package roflcopter import ( "bytes" _ "embed" "io" "log" "sync" "time" "github.com/faiface/beep/mp3" "github.com/faiface/beep/speaker" ) //go:embed embed\swah.mp3 var swah []byte var ( work bool = true duration time.Duration inWork *sync.WaitGroup ) const ( frame1 = " ROFL:ROFL: \n _^____ \n L __/ [] \\ \n O ===__ \\ \n L \\________] \n I I \n --------/ \n" frame2 = " :ROFL:ROFL\n _^____ \n __/ [] \\ \nLOL===__ \\ \n \\________] \n I I \n --------/ \n" ) type Roflcopter struct { work bool count time.Duration str *string runner func() } // NewRoflcopter creates a new instance of roflcopter. amount sets duration, outStr is used to output frames, funcrunner will be called after frame change func NewRoflcopter(amount time.Duration, outStr *string, funcrunner func()) *Roflcopter { inWork = new(sync.WaitGroup) return &Roflcopter{ work: true, str: outStr, count: amount, runner: funcrunner, } } // Start starts frame changing. Soundplaying can be set by true or false. Returns WaitGroup to know when it has finished work. func (b *Roflcopter) Start(playSound bool) *sync.WaitGroup { var wg *sync.WaitGroup = new(sync.WaitGroup) inWork.Add(1) *b.str = frame1 + b.count.String() work = b.work duration = b.count if playSound { go b.player(wg) } go b.timeCounter(500 * time.Millisecond) go b.frameChanger(125 * time.Millisecond) return inWork } // OnlySound only plays sound. Frames are not changing. Returns WaitGroup to know when it has finished work func (b *Roflcopter) OnlySound() *sync.WaitGroup { var wg *sync.WaitGroup = new(sync.WaitGroup) inWork.Add(1) work = b.work duration = b.count go b.player(wg) go b.timeCounter(500 * time.Millisecond) return inWork } // timeCounter counts time and stops other work when time ends func (b *Roflcopter) timeCounter(step time.Duration) { for duration > 0 { duration -= step time.Sleep(step) } work = false time.Sleep(100 * time.Millisecond) } //player is a loop to start sound play func (b *Roflcopter) player(wg *sync.WaitGroup) { b.sound(wg) wg.Wait() if work { b.player(wg) } else { inWork.Done() } } //frameChanger is a loop to change frames func (b *Roflcopter) frameChanger(delay time.Duration) { nextframe := 2 for work { switch nextframe { case 1: { *b.str = frame1 + "Ends in " + duration.String() time.Sleep(delay) nextframe = 2 } case 2: { *b.str = frame2 + "Ends in " + duration.String() time.Sleep(delay) nextframe = 1 } } b.runner() } inWork.Done() } //sound plays sound func (b *Roflcopter) sound(wg *sync.WaitGroup) { wg.Add(1) t := 1*time.Second + 380*time.Millisecond streamer, format, err := mp3.Decode(io.NopCloser(bytes.NewReader(swah))) if err != nil { log.Fatal(err) } defer streamer.Close() speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10)) speaker.Play(streamer) time.Sleep(t * 1) wg.Done() }