telnet.go 2.5 KB

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