telnet.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package liquidsoap
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "strings"
  7. )
  8. // Client represents a telnet/unix domain connection to Liquidsoap
  9. //
  10. // A Client can perform low-level operations, such as Command(), or high-level operations such as Outputs()
  11. type Client struct {
  12. Conn net.Conn
  13. }
  14. // NewTelnet returns a liquidsoap.Client created using telnet on the given parameters
  15. func NewTelnet(host string, port int) (Client, error) {
  16. conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
  17. if err != nil {
  18. return Client{}, err
  19. }
  20. return Client{Conn: conn}, nil
  21. }
  22. // Close closes the connection
  23. func (c *Client) Close() {
  24. if c.Conn != nil {
  25. c.Conn.Write([]byte("quit\n"))
  26. c.Conn.Close()
  27. }
  28. }
  29. // Command run a command, wait for output response to come and returns it
  30. func (c *Client) Command(cmdline string) (string, error) {
  31. c.Conn.Write([]byte(cmdline + "\n"))
  32. var out, line string
  33. var err error
  34. reader := bufio.NewReader(c.Conn)
  35. for {
  36. if line, err = reader.ReadString('\n'); err != nil {
  37. return "", err
  38. }
  39. line = line[:len(line)-2] + "\n" // \r\n -> \n
  40. if line == "END\n" {
  41. return out, nil
  42. }
  43. out += line
  44. }
  45. }
  46. // Outputs will return a map of outputs that liquidsoap is handling.
  47. // An output is set to true if it is enabled
  48. func (c *Client) Outputs() (outputs map[string]bool, err error) {
  49. outputs = make(map[string]bool)
  50. var cmdout string
  51. cmdout, err = c.Command("list")
  52. if err != nil {
  53. return
  54. }
  55. lines := strings.Split(cmdout, "\n")
  56. for _, l := range lines {
  57. parts := strings.SplitN(l, " : ", 2)
  58. if len(parts) < 2 {
  59. continue
  60. }
  61. if strings.Index(parts[1], "output.") == 0 {
  62. name := strings.TrimSpace(parts[0])
  63. var enabled bool
  64. enabled, err = c.GetOutput(name)
  65. if err != nil {
  66. return
  67. }
  68. outputs[name] = enabled
  69. }
  70. }
  71. return
  72. }
  73. // GetOutput checks whether an output is enabled
  74. func (c *Client) GetOutput(name string) (bool, error) {
  75. cmdout, err := c.Command(name + ".status")
  76. if err != nil {
  77. return false, err
  78. }
  79. return strings.TrimSpace(cmdout) == "on", nil
  80. }
  81. // SetOutput enables or disables an output
  82. func (c *Client) SetOutput(name string, enabled bool) error {
  83. action := "stop"
  84. if enabled {
  85. action = "start"
  86. }
  87. cmdout, err := c.Command(fmt.Sprintf("%s.%s", name, action))
  88. if err != nil {
  89. return err
  90. }
  91. if strings.TrimSpace(cmdout) != "OK" {
  92. return fmt.Errorf("Error: liquidsoap replied '%s'", cmdout)
  93. }
  94. return nil
  95. }