media.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "os/exec"
  6. // osc
  7. "github.com/hypebeast/go-osc/osc"
  8. )
  9. // Base structure for audiovisual media.
  10. // Media is simply a file containing audio and video material.
  11. type Media struct {
  12. active bool
  13. cmd *exec.Cmd
  14. args []string
  15. }
  16. // Interface for Media type structs
  17. type MediaPlayer interface {
  18. play()
  19. stop()
  20. }
  21. // Run executable
  22. func run(name string, args ...string) *exec.Cmd {
  23. // Find executable
  24. //path, err := exec.LookPath(name)
  25. //if err != nil {
  26. // log.Printf("can't find '%s'\n", name)
  27. // return nil
  28. //}
  29. //println("got path")
  30. //log.Println("got path:", path, args)
  31. cmd := exec.Command(name, args...)
  32. if err := cmd.Run(); err != nil {
  33. log.Print(err)
  34. return nil
  35. }
  36. return cmd
  37. }
  38. // Run executable
  39. func (player *Media) run(name string, args ...string) {
  40. player.cmd = exec.Command(name, args...)
  41. if err := player.cmd.Run(); err != nil {
  42. log.Print(err)
  43. }
  44. }
  45. // Play media file via mpv, osc message sets the file path
  46. func (player *Media) play(msg *osc.Message) {
  47. if player.active {
  48. log.Print("please stop current player before playing another")
  49. log.Print(player.cmd)
  50. return
  51. }
  52. uri := getOSC[string](msg)
  53. osc.PrintMessage(msg)
  54. if uri == "" {
  55. log.Print("player won't play without uri")
  56. return
  57. }
  58. player.active = true
  59. // you can route audio directly through alsa/hdmi but beware of clipping
  60. //run(player, "mpv", "-fs", "--audio-device=alsa/hdmi", "--volume=25", uri)
  61. args := append(player.args, uri)
  62. player.run(args[0], args[1:]...)
  63. player.active = false
  64. }
  65. // Stop the player by shutting down MPV
  66. func (player *Media) stop(msg *osc.Message) {
  67. player.quit()
  68. }
  69. // Change volume using amixer command
  70. func (player *Media) volume(msg *osc.Message) {
  71. level := getOSC[float32](msg)
  72. run("amixer", "-q", "sset", "Master", fmt.Sprintf("%.2f%%", level*100.0))
  73. }
  74. func (player *Media) quit() {
  75. if !player.active {
  76. log.Print("can't kill player if it ain't running")
  77. return
  78. }
  79. if err := player.cmd.Process.Kill(); err != nil {
  80. log.Print("failed to kill process: ", err)
  81. }
  82. player.active = false
  83. }
  84. func NewMPV() *Media {
  85. media := new(Media)
  86. media.args = []string{"mpv", "-fs"}
  87. return media
  88. }
  89. func NewXLEmulator() *Media {
  90. media := new(Media)
  91. media.args = []string{"atari800", "-stretch", "3"}
  92. return media
  93. }