volume_linux.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // +build !windows,!darwin
  2. /*
  3. * Copied from https://github.com/itchyny/volume-go, MIT License
  4. */
  5. package Sound
  6. import (
  7. "errors"
  8. "os/exec"
  9. "regexp"
  10. "strconv"
  11. "strings"
  12. )
  13. var useAmixer bool
  14. func init() {
  15. if _, err := exec.LookPath("pactl"); err != nil {
  16. useAmixer = true
  17. }
  18. }
  19. func getVolumeCmd() []string {
  20. if useAmixer {
  21. return []string{"amixer", "get", "Master"}
  22. }
  23. return []string{"pactl", "list", "sinks"}
  24. }
  25. var volumePattern = regexp.MustCompile(`\d+%`)
  26. func parseVolume(out string) (int, error) {
  27. lines := strings.Split(out, "\n")
  28. for _, line := range lines {
  29. s := strings.TrimLeft(line, " \t")
  30. if useAmixer && strings.Contains(s, "Playback") && strings.Contains(s, "%") ||
  31. !useAmixer && strings.HasPrefix(s, "Volume:") {
  32. volumeStr := volumePattern.FindString(s)
  33. return strconv.Atoi(volumeStr[:len(volumeStr)-1])
  34. }
  35. }
  36. return 0, errors.New("no volume found")
  37. }
  38. func setVolumeCmd(volume int) []string {
  39. if useAmixer {
  40. return []string{"amixer", "set", "Master", strconv.Itoa(volume) + "%"}
  41. }
  42. return []string{"pactl", "set-sink-volume", "0", strconv.Itoa(volume) + "%"}
  43. }
  44. func increaseVolumeCmd(diff int) []string {
  45. var sign string
  46. if diff >= 0 {
  47. sign = "+"
  48. } else if useAmixer {
  49. diff = -diff
  50. sign = "-"
  51. }
  52. if useAmixer {
  53. return []string{"amixer", "set", "Master", strconv.Itoa(diff) + "%" + sign}
  54. }
  55. return []string{"pactl", "--", "set-sink-volume", "0", sign + strconv.Itoa(diff) + "%"}
  56. }
  57. func getMutedCmd() []string {
  58. if useAmixer {
  59. return []string{"amixer", "get", "Master"}
  60. }
  61. return []string{"pactl", "list", "sinks"}
  62. }
  63. func parseMuted(out string) (bool, error) {
  64. lines := strings.Split(out, "\n")
  65. for _, line := range lines {
  66. s := strings.TrimLeft(line, " \t")
  67. if useAmixer && strings.Contains(s, "Playback") && strings.Contains(s, "%") ||
  68. !useAmixer && strings.HasPrefix(s, "Mute: ") {
  69. if strings.Contains(s, "[off]") || strings.Contains(s, "yes") {
  70. return true, nil
  71. } else if strings.Contains(s, "[on]") || strings.Contains(s, "no") {
  72. return false, nil
  73. }
  74. }
  75. }
  76. return false, errors.New("no muted information found")
  77. }
  78. func muteCmd() []string {
  79. if useAmixer {
  80. return []string{"amixer", "-D", "pulse", "set", "Master", "mute"}
  81. }
  82. return []string{"pactl", "set-sink-mute", "0", "1"}
  83. }
  84. func unmuteCmd() []string {
  85. if useAmixer {
  86. return []string{"amixer", "-D", "pulse", "set", "Master", "unmute"}
  87. }
  88. return []string{"pactl", "set-sink-mute", "0", "0"}
  89. }