// OnUserChange event. Checks UserChange type, and adjusts items such as skiplists to reflect // the current status of the users on the server. func (dj *mumbledj) OnUserChange(e *gumble.UserChangeEvent) { if e.Type.Has(gumble.UserChangeDisconnected) { if dj.audioStream.IsPlaying() { if !isNil(dj.queue.CurrentSong().Playlist()) { dj.queue.CurrentSong().Playlist().RemoveSkip(e.User.Name) } dj.queue.CurrentSong().RemoveSkip(e.User.Name) } } else if (e.Type.Has(gumble.UserChangeConnected) || e.Type.Has(gumble.UserChangeChannel)) && e.User.Channel == dj.client.Self.Channel { // Play welcome message if !dj.audioStream.IsPlaying() { var filename = "" if _, err := os.Stat(dj.homeDir + "/.mumbledj/greetings/" + e.User.Name + ".mp3"); os.IsNotExist(err) { // Check for custom welcome message filename = "default.mp3" // If file does not exist } else { filename = e.User.Name + ".mp3" // If file exists } if _, err := os.Stat(fmt.Sprintf("%s/.mumbledj/greetings/%s", dj.homeDir, filename)); os.IsNotExist(err) { } else { dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/.mumbledj/greetings/%s", dj.homeDir, filename)) if err := dj.audioStream.Play(); err != nil { panic(err) } else { go func() { dj.audioStream.Wait() if dj.queue.Len() >= 1 { dj.queue.PrepareAndPlayNextSong() } }() } } } } }
//Uses text-to-speech to have Jewvis speak func Say(user *gumble.User, speech string) { c1 := exec.Command("echo", fmt.Sprint(speech)) c2 := exec.Command("text2wave", "-o", fmt.Sprintf("%s/jewvis/clips/speech.wav", jew.homeDir), "-scale", "3") r, w := io.Pipe() c1.Stdout = w c2.Stdin = r var b2 bytes.Buffer c2.Stdout = &b2 c1.Start() c2.Start() c1.Wait() w.Close() c2.Wait() io.Copy(os.Stdout, &b2) PlayClip(user, "speech.wav", true) jew.audioStream.Volume = 0.8 jew.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/jewvis/clips/speech.wav", jew.homeDir)) if err := jew.audioStream.Play(); err != nil { errors.New("Clip not found/can't be played") } jew.audioStream.Volume = jew.conf.Volume.DefaultVolume }
func (p *Plugin) apiAudioPlay(l *lua.State) int { if p.instance.Audio.IsPlaying() { l.PushBoolean(false) return 1 } obj := luar.NewLuaObject(l, 1) filename := obj.Get("filename").(string) callback := obj.GetObject("callback") obj.Close() if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { enc.SetApplication(gopus.Audio) } p.instance.Audio.Source = gumble_ffmpeg.SourceFile(filename) p.instance.Audio.Play() go func() { p.instance.Audio.Wait() if callback.Type != "nil" { p.callValue(callback) } callback.Close() }() return 0 }
func (p *Plugin) apiAudioPlay(call otto.FunctionCall) otto.Value { if p.instance.Audio.IsPlaying() { return otto.FalseValue() } obj := call.Argument(0).Object() if obj == nil { return otto.FalseValue() } filenameValue, _ := obj.Get("filename") callbackValue, _ := obj.Get("callback") if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { enc.SetApplication(gopus.Audio) } p.instance.Audio.Source = gumble_ffmpeg.SourceFile(filenameValue.String()) p.instance.Audio.Play() go func() { p.instance.Audio.Wait() if callbackValue.IsFunction() { p.callValue(callbackValue) } }() return otto.TrueValue() }
// Plays a tts clip of the inputed text func TTS(user *gumble.User, argument string) { a, err := watsonService.Synthesize(argument, jew.conf.General.TTSVoice, "wav") if err != nil { fmt.Println(err) } defer a.Close() f, err := os.Create("/home/orion/jewbot/songs/tts.wav") if err != nil { fmt.Println(err) } defer f.Close() _, err = io.Copy(f, a) if err != nil { fmt.Println(err) } if !jew.audioStream.IsPlaying() { jew.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/jewbot/songs/tts.wav", jew.homeDir)) if err := jew.audioStream.Play(); err != nil { panic(err) } } }
func PlayAnthem(user *gumble.User) { jew.audioStream.Volume = 0.8 Source := fmt.Sprintf("%s/jewvis/clips/%s", jew.homeDir, m[user.Name]) jew.audioStream.Source = gumble_ffmpeg.SourceFile(Source) if err := jew.audioStream.Play(); err != nil { errors.New("err") } }
func PlayClip(user *gumble.User, argument string, name bool) error { //Specific name called clips to avoid playing wrong clip if name { jew.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/jewvis/clips/%s", jew.homeDir, argument)) if err := jew.audioStream.Play(); err != nil { errors.New("Clip not found/can't be played") } return nil } //Read into file and display possible clips files, _ := ioutil.ReadDir(fmt.Sprintf("%s/jewvis/clips", jew.homeDir)) message := `<ol><br><b><h1 style="color:cyan">CLIPS</b></h1> <br>Use .play "clip number" to play clip.<br>` for _, f := range files { message += fmt.Sprintf("<li>%s</li>", f.Name()) } message += "</ol>" if argument == "" { jew.SendPM(user, message) return nil } else { //Play clip n, err := strconv.Atoi(argument) if err == nil && n > 0 && n <= len(files) { //Create slice of song names from map of files for _, f := range files { anthem = append(anthem, f.Name()) } //Play clip Source := fmt.Sprintf("%s/jewvis/clips/%s", jew.homeDir, anthem[n-1]) jew.audioStream.Source = gumble_ffmpeg.SourceFile(Source) if err := jew.audioStream.Play(); err != nil { return errors.New("Cannot play") } } else { jew.client.Self.Channel.Send("Enter a feasible number", false) return errors.New("Not a page number") } return nil } }
//Plays Youtube clips func PlayYoutube(offset string, shortURL string) { NumOffset, err := strconv.Atoi(offset) if err == nil { offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", NumOffset)) jew.audioStream.Offset = offsetDuration } jew.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/jewvis/clips/youtube.m4a", jew.homeDir)) if err := jew.audioStream.Play(); err != nil { panic(err) } }
// Play plays the song. Once the song is playing, a notification is displayed in a text message that features the video // thumbnail, URL, title, duration, and submitter. func (s *YouTubeSong) Play() { if s.offset != 0 { offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", s.offset)) dj.audioStream.Offset = offsetDuration } dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, s.Filename())) if err := dj.audioStream.Play(); err != nil { panic(err) } else { if s.Playlist() == nil { message := ` <table> <tr> <td align="center"><img src="%s" width=150 /></td> </tr> <tr> <td align="center"><b><a href="http://youtu.be/%s">%s</a> (%s)</b></td> </tr> <tr> <td align="center">Added by %s</td> </tr> </table> ` dj.client.Self.Channel.Send(fmt.Sprintf(message, s.Thumbnail(), s.ID(), s.Title(), s.Duration(), s.Submitter()), false) } else { message := ` <table> <tr> <td align="center"><img src="%s" width=150 /></td> </tr> <tr> <td align="center"><b><a href="http://youtu.be/%s">%s</a> (%s)</b></td> </tr> <tr> <td align="center">Added by %s</td> </tr> <tr> <td align="center">From playlist "%s"</td> </tr> </table> ` dj.client.Self.Channel.Send(fmt.Sprintf(message, s.Thumbnail(), s.ID(), s.Title(), s.Duration(), s.Submitter(), s.Playlist().Title()), false) } go func() { dj.audioStream.Wait() dj.queue.OnSongFinished() }() } }
func (p *Plugin) apiAudioPlay(tbl *lua.LTable) bool { if p.instance.Audio.IsPlaying() { return false } filename := tbl.RawGetH(lua.LString("filename")) exec := tbl.RawGetH(lua.LString("exec")) args := tbl.RawGetH(lua.LString("args")) callback := tbl.RawGetH(lua.LString("callback")) if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { enc.SetApplication(gopus.Audio) } switch { // source file case filename != lua.LNil && exec == lua.LNil && args == lua.LNil: p.instance.Audio.Source = gumble_ffmpeg.SourceFile(filename.String()) // source exec case filename == lua.LNil && exec != lua.LNil: var argsStr []string if argsTable, ok := args.(*lua.LTable); ok { for i := 1; ; i++ { arg := argsTable.RawGetInt(i) if arg == lua.LNil { break } argsStr = append(argsStr, arg.String()) } } p.instance.Audio.Source = gumble_ffmpeg.SourceExec(exec.String(), argsStr...) default: panic("invalid source type") } p.instance.Audio.Play() go func() { p.instance.Audio.Wait() if callback.Type() != lua.LTNil { p.callValue(callback) } }() return true }
func main() { files := make(map[string]string) var stream *gumble_ffmpeg.Stream flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s: [flags] [audio files...]\n", os.Args[0]) flag.PrintDefaults() } gumbleutil.Main(func(client *gumble.Client) { stream = gumble_ffmpeg.New(client) client.Attach(gumbleutil.AutoBitrate) for _, file := range flag.Args() { key := filepath.Base(file) files[key] = file } }, gumbleutil.Listener{ // Connect event Connect: func(e *gumble.ConnectEvent) { fmt.Printf("audio player loaded! (%d files)\n", len(files)) }, // Text message event TextMessage: func(e *gumble.TextMessageEvent) { if e.Sender == nil { return } file, ok := files[e.Message] if !ok { return } stream.Source = gumble_ffmpeg.SourceFile(file) if err := stream.Play(); err != nil { fmt.Printf("%s\n", err) } else { fmt.Printf("Playing %s\n", file) } }, }) }
// Play plays the song. Once the song is playing, a notification is displayed in a text message that features the song // thumbnail, URL, title, duration, and submitter. func (dl *AudioTrack) Play() { if dl.offset != 0 { offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", dl.offset)) dj.audioStream.Offset = offsetDuration } dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, dl.Filename())) if err := dj.audioStream.Play(); err != nil { panic(err) } else { message := `<table><tr><td align="center"><img src="%s" width=150 /></td></tr><tr><td align="center"><b><a href="%s">%s</a> (%s)</b></td></tr><tr><td align="center">Added by %s</td></tr>` message = fmt.Sprintf(message, dl.thumbnail, dl.url, dl.title, dl.Duration().String(), dl.submitter.Name) if !isNil(dl.playlist) { message = fmt.Sprintf(message+`<tr><td align="center">From playlist "%s"</td></tr>`, dl.Playlist().Title()) } dj.client.Self.Channel.Send(message+`</table>`, false) go func() { dj.audioStream.Wait() dj.queue.OnSongFinished() }() } }