diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | COPYING | 3 | ||||
-rw-r--r-- | README.md | 36 | ||||
-rw-r--r-- | ff2mpv.go | 103 | ||||
-rw-r--r-- | ff2mpv_386.go | 5 | ||||
-rw-r--r-- | ff2mpv_amd64.go | 5 | ||||
-rw-r--r-- | ff2mpv_arm.go | 5 | ||||
-rw-r--r-- | ff2mpv_arm64.go | 5 | ||||
-rw-r--r-- | go.mod | 1 |
9 files changed, 164 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..585f016 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/ff2mpv-go @@ -0,0 +1,3 @@ +This software is released into the public domain. +It is provided "as is", without warranties or conditions of any kind. +Anyone is free to use, modify, redistribute and do anything with this software. diff --git a/README.md b/README.md new file mode 100644 index 0000000..821bf90 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +ff2mpv-go +========= + +Native messaging host for [ff2mpv](https://github.com/woodruffw/ff2mpv/) written in Go. + +Since it is a native binary, it starts faster than the official Python or Ruby +implementations. + + +Requirements +------------ + +- [Firefox](https://www.mozilla.org/en-US/firefox/) 50 or later +- [ff2mpv](https://github.com/woodruffw/ff2mpv/) 3.0 or later +- [Go](https://golang.org/) 11 or later (probably works on older versions too) +- [mpv](https://mpv.io/) 0.21.0 or later + + +Installation +------------ + +- `go get git.clsr.net/util/ff2mpv-go` +- `ff2mpv-go --manifest > ~/.mozilla/native-messaging-hosts/ff2mpv.json` + +If `$GOBIN` is not in `$PATH`, specify the full path to the installed +executable (e.g. `$GOBIN/ff2mpv-go`) when running it. + +If a custom mpv command is required, manually clone the repository and edit the +`mpvCmd` variable in `ff2mpv.go`, then `go install` the package instead of the +`go get` step. + + +Usage +----- + +Use ff2mpv as normally. diff --git a/ff2mpv.go b/ff2mpv.go new file mode 100644 index 0000000..7f0c939 --- /dev/null +++ b/ff2mpv.go @@ -0,0 +1,103 @@ +package main + +import ( + "encoding/binary" + "encoding/json" + "fmt" + "io" + "os" + "os/exec" +) + +var mpvCmd = []string{"mpv", "--player-operation-mode=pseudo-gui", "--"} + +type ffRequest struct { + URL string `json:"url"` +} + +type ffManifest struct { + Name string `json:"name"` + Description string `json:"description"` + Path string `json:"path"` + Type string `json:"type"` + AllowedExtensions []string `json:"allowed_extensions"` +} + +func ff2mpv() { + // extract message length from the first 4 bytes + var l uint32 + // Go does not have an easy way to do sutff with native endianness without + // using usafe. Blame stupid WebExtension spec that uses *native* endianness in + // a *protocol*. Seriously, who designed that‽ + if err := binary.Read(os.Stdin, endianness, &l); err != nil { + panic(err) + } + if l > 1024*1024 { + panic(fmt.Sprintf("native messaging message length too large: %d", l)) + } + + // read raw message + buf := make([]byte, l) + if n, err := os.Stdin.Read(buf); err != nil { + panic(err) + } else if n != len(buf) { + panic(fmt.Sprintf("read message length %d does not match expected length %d", n, l)) + } + + // decode JSON + var data ffRequest + if err := json.Unmarshal(buf, &data); err != nil { + panic(err) + } + + // run mpv + args := append(mpvCmd, data.URL) + cmd := exec.Command(args[0], args[1:]...) + if err := cmd.Start(); err != nil { + panic(err) + } + + // respond + outmsg := []byte("{}") + outlen := uint32(len(outmsg)) + binary.Write(os.Stdout, endianness, outlen) + os.Stdout.Write(outmsg) +} + +func manifest() { + exe, err := os.Executable() + if err != nil { + panic(err) + } + data, err := json.MarshalIndent(ffManifest{ + Name: "ff2mpv", + Description: "ff2mpv's extenal manifest (ff2mpv-go)", + Path: exe, + Type: "stdio", + AllowedExtensions: []string{"ff2mpv@yossarian.net"}, + }, "", "\t") + if err != nil { + panic(err) + } + os.Stdout.Write(data) +} + +func usage(w io.Writer) { + fmt.Fprintf(os.Stderr, "args: %#v\n", os.Args) + fmt.Fprintf(w, "usage: %s [--manifest]\n", os.Args[0]) +} + +func main() { + arg := "" + if len(os.Args) == 2 { + arg = os.Args[1] + } + switch arg { + case "--manifest": + manifest() + case "--help": + usage(os.Stdout) + default: + ff2mpv() + } +} diff --git a/ff2mpv_386.go b/ff2mpv_386.go new file mode 100644 index 0000000..4e77e9a --- /dev/null +++ b/ff2mpv_386.go @@ -0,0 +1,5 @@ +package main + +import "encoding/binary" + +var endianness = binary.LittleEndian diff --git a/ff2mpv_amd64.go b/ff2mpv_amd64.go new file mode 100644 index 0000000..4e77e9a --- /dev/null +++ b/ff2mpv_amd64.go @@ -0,0 +1,5 @@ +package main + +import "encoding/binary" + +var endianness = binary.LittleEndian diff --git a/ff2mpv_arm.go b/ff2mpv_arm.go new file mode 100644 index 0000000..4e77e9a --- /dev/null +++ b/ff2mpv_arm.go @@ -0,0 +1,5 @@ +package main + +import "encoding/binary" + +var endianness = binary.LittleEndian diff --git a/ff2mpv_arm64.go b/ff2mpv_arm64.go new file mode 100644 index 0000000..4e77e9a --- /dev/null +++ b/ff2mpv_arm64.go @@ -0,0 +1,5 @@ +package main + +import "encoding/binary" + +var endianness = binary.LittleEndian @@ -0,0 +1 @@ +module git.clsr.net/util/ff2mpv-go |