// Copyright 2016 The Periph Authors. All rights reserved. // Use of this source code is governed under the Apache License, Version 2.0 // that can be found in the LICENSE file. package lirc import ( "bufio" "fmt" "log" "net" "strconv" "strings" "sync" "periph.io/x/conn/v3" "periph.io/x/conn/v3/ir" ) // New returns a IR receiver / emitter handle. func New() (*Conn, error) { w, err := net.Dial("unix", "/var/run/lirc/lircd") if err != nil { return nil, err } c := &Conn{w: w, c: make(chan ir.Message), list: map[string][]string{}} // Unconditionally retrieve the list of all known keys at start. if _, err := w.Write([]byte("LIST\n")); err != nil { _ = w.Close() return nil, err } go c.loop(bufio.NewReader(w)) return c, nil } // Conn is an open port to lirc. type Conn struct { w net.Conn c chan ir.Message mu sync.Mutex list map[string][]string // list of remotes and associated keys pendingList map[string][]string // list of remotes and associated keys being created. } // String implements conn.Resource. func (c *Conn) String() string { return "lirc" } // Halt implements conn.Resource. // // It has no effect. func (c *Conn) Halt() error { return nil } // Close closes the socket to lirc. It is not a requirement to close before // process termination. func (c *Conn) Close() error { return c.w.Close() } // Emit implements ir.IR. func (c *Conn) Emit(remote string, key ir.Key) error { // http://www.lirc.org/html/lircd.html#lbAH _, err := fmt.Fprintf(c.w, "SEND_ONCE %s %s\n", remote, key) return err } // Channel implements ir.IR. func (c *Conn) Channel() <-chan ir.Message { return c.c } // Codes returns all the known codes. // // Empty if the list was not retrieved yet. func (c *Conn) Codes() map[string][]string { c.mu.Lock() defer c.mu.Unlock() return c.list } // func (c *Conn) loop(r *bufio.Reader) { defer func() { close(c.c) c.c = nil }() for { line, err := read(r) if line == "BEGIN" { err = c.readData(r) } else if len(line) != 0 { // Format is: