Skip to content

Commit

Permalink
Fully deprecated the goupnp/soap package. Fixed some Windows compatib…
Browse files Browse the repository at this point in the history
…ility issues. Improved the subtitles support and error handling.
  • Loading branch information
alexballas committed Feb 12, 2021
1 parent 1cfcb5b commit 0bef5b3
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 44 deletions.
50 changes: 36 additions & 14 deletions flagfuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"net/url"
"os"
"path/filepath"
"runtime"
"sort"
)

Expand All @@ -25,44 +27,56 @@ func listFlagFunction() error {
sort.Ints(keys)

for _, k := range keys {
fmt.Printf("\033[1mDevice %v\033[0m\n", k)
fmt.Printf("\033[1m--------\033[0m\n")
fmt.Printf("\033[1mModel\033[0m: %s\n", devices[k][0])
fmt.Printf("\033[1mURL\033[0m: %s\n", devices[k][1])
boldStart := ""
boldEnd := ""

if runtime.GOOS == "linux" {
boldStart = "\033[1m"
boldEnd = "\033[0m"
}
fmt.Printf("%sDevice %v%s\n", boldStart, k, boldEnd)
fmt.Printf("%s--------%s\n", boldStart, boldEnd)
fmt.Printf("%sModel:%s %s\n", boldStart, boldEnd, devices[k][0])
fmt.Printf("%sURL:%s %s\n", boldStart, boldEnd, devices[k][1])
fmt.Println()
}
return nil
}

func checkflags() (bool, error) {
if err := checkVflag(); err != nil {
return false, err
}

if err := checkTflag(); err != nil {
return false, err
}

list, err := checkLflag()
if err != nil {
return false, err
}

if list == true {
return true, nil
}

if err := checkVflag(); err != nil {
return false, err
}

if err := checkSflag(); err != nil {
return false, err
}

return false, nil
}

func checkVflag() error {
if *videoArg == "" {
err := errors.New("No video file defined")
return err
}
if _, err := os.Stat(*videoArg); os.IsNotExist(err) {
return err
if *listPtr == false {
if *videoArg == "" {
err := errors.New("No video file defined")
return err
}
if _, err := os.Stat(*videoArg); os.IsNotExist(err) {
return err
}
}
return nil
}
Expand All @@ -72,6 +86,14 @@ func checkSflag() error {
if _, err := os.Stat(*subsArg); os.IsNotExist(err) {
return err
}
} else {
// The checkVflag should happen before
// checkSflag so we're safe to call *videoArg
// here. If *subsArg is empty, try to
// automatically find the srt from the
// video filename.
*subsArg = (*videoArg)[0:len(*videoArg)-
len(filepath.Ext(*videoArg))] + ".srt"
}
return nil
}
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/alexballas/go2tv
go 1.15

require (
github.com/huin/goupnp v1.0.0
github.com/koron/go-ssdp v0.0.2
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
)
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o=
github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
Expand Down
1 change: 1 addition & 0 deletions go2tv.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func main() {
go func() { s.ServeFiles(serverStarted, absVideoFile, absSubtitlesFile) }()
// Wait for HTTP server to properly initialize
<-serverStarted

if err := tvdata.SendtoTV("Play"); err != nil {
fmt.Fprintf(os.Stderr, "Encountered error(s): %s\n", err)
os.Exit(1)
Expand Down
8 changes: 4 additions & 4 deletions servefiles/servefiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ func (f *filesToServe) serveSubtitlesHandler(w http.ResponseWriter, req *http.Re
filePath, err := os.Open(f.Subtitles)
defer filePath.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Encountered error(s): %s\n", err)
os.Exit(1)
http.Error(w, "", 404)
return
}

fileStat, err := filePath.Stat()
if err != nil {
fmt.Fprintf(os.Stderr, "Encountered error(s): %s\n", err)
os.Exit(1)
http.Error(w, "", 404)
return
}
http.ServeContent(w, req, filepath.Base(f.Subtitles), fileStat.ModTime(), filePath)

Expand Down
113 changes: 108 additions & 5 deletions soapcalls/soapbuilders.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,65 @@ import (
"fmt"
)

type Envelope struct {
// PlayEnvelope - As in Play Pause Stop
type PlayEnvelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Schema string `xml:"xmlns:s,attr"`
Encoding string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
PlayBody PlayBody `xml:"s:Body"`
}

type Body struct {
// PlayBody .
type PlayBody struct {
XMLName xml.Name `xml:"s:Body"`
PlayAction PlayAction `xml:"u:Play"`
}

// PlayAction .
type PlayAction struct {
XMLName xml.Name `xml:"u:Play"`
AVTransport string `xml:"xmlns:u,attr"`
InstanceID string
Speed string
}

// StopEnvelope - As in Play Pause Stop
type StopEnvelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Schema string `xml:"xmlns:s,attr"`
Encoding string `xml:"s:encodingStyle,attr"`
StopBody StopBody `xml:"s:Body"`
}

// StopBody .
type StopBody struct {
XMLName xml.Name `xml:"s:Body"`
StopAction StopAction `xml:"u:Stop"`
}

// StopAction .
type StopAction struct {
XMLName xml.Name `xml:"u:Stop"`
AVTransport string `xml:"xmlns:u,attr"`
InstanceID string
Speed string
}

// SetAVTransportEnvelope .
type SetAVTransportEnvelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Schema string `xml:"xmlns:s,attr"`
Encoding string `xml:"s:encodingStyle,attr"`
Body SetAVTransportBody `xml:"s:Body"`
}

// SetAVTransportBody .
type SetAVTransportBody struct {
XMLName xml.Name `xml:"s:Body"`
SetAVTransportURI SetAVTransportURI `xml:"u:SetAVTransportURI"`
}

// SetAVTransportURI .
type SetAVTransportURI struct {
XMLName xml.Name `xml:"u:SetAVTransportURI"`
AVTransport string `xml:"xmlns:u,attr"`
Expand All @@ -26,11 +73,13 @@ type SetAVTransportURI struct {
CurrentURIMetaData CurrentURIMetaData `xml:"CurrentURIMetaData"`
}

// CurrentURIMetaData .
type CurrentURIMetaData struct {
XMLName xml.Name `xml:"CurrentURIMetaData"`
Value []byte `xml:",chardata"`
}

// DIDLLite .
type DIDLLite struct {
XMLName xml.Name `xml:"DIDL-Lite"`
SchemaDIDL string `xml:"xmlns,attr"`
Expand All @@ -40,6 +89,7 @@ type DIDLLite struct {
DIDLLiteItem DIDLLiteItem `xml:"item"`
}

// DIDLLiteItem .
type DIDLLiteItem struct {
XMLName xml.Name `xml:"item"`
ID string `xml:"id,attr"`
Expand All @@ -52,18 +102,21 @@ type DIDLLiteItem struct {
SecCaptionInfoEx SecCaptionInfoEx `xml:"sec:CaptionInfoEx"`
}

// ResNode .
type ResNode struct {
XMLName xml.Name `xml:"res"`
ProtocolInfo string `xml:"protocolInfo,attr"`
Value string `xml:",chardata"`
}

// SecCaptionInfo .
type SecCaptionInfo struct {
XMLName xml.Name `xml:"sec:CaptionInfo"`
Type string `xml:"sec:type,attr"`
Value string `xml:",chardata"`
}

// SecCaptionInfoEx .
type SecCaptionInfoEx struct {
XMLName xml.Name `xml:"sec:CaptionInfoEx"`
Type string `xml:"sec:type,attr"`
Expand Down Expand Up @@ -112,11 +165,11 @@ func setAVTransportSoapBuild(videoURL, subtitleURL string) ([]byte, error) {
return make([]byte, 0), err
}

d := Envelope{
d := SetAVTransportEnvelope{
XMLName: xml.Name{},
Schema: "http://schemas.xmlsoap.org/soap/envelope/",
Encoding: "http://schemas.xmlsoap.org/soap/encoding/",
Body: Body{
Body: SetAVTransportBody{
XMLName: xml.Name{},
SetAVTransportURI: SetAVTransportURI{
XMLName: xml.Name{},
Expand All @@ -142,3 +195,53 @@ func setAVTransportSoapBuild(videoURL, subtitleURL string) ([]byte, error) {

return append(xmlStart, b...), nil
}

func playSoapBuild() ([]byte, error) {
d := PlayEnvelope{
XMLName: xml.Name{},
Schema: "http://schemas.xmlsoap.org/soap/envelope/",
Encoding: "http://schemas.xmlsoap.org/soap/encoding/",
PlayBody: PlayBody{
XMLName: xml.Name{},
PlayAction: PlayAction{
XMLName: xml.Name{},
AVTransport: "urn:schemas-upnp-org:service:AVTransport:1",
InstanceID: "0",
Speed: "1",
},
},
}
xmlStart := []byte("<?xml version='1.0' encoding='utf-8'?>")
b, err := xml.Marshal(d)
if err != nil {
fmt.Println(err)
return make([]byte, 0), err
}

return append(xmlStart, b...), nil
}

func stopSoapBuild() ([]byte, error) {
d := StopEnvelope{
XMLName: xml.Name{},
Schema: "http://schemas.xmlsoap.org/soap/envelope/",
Encoding: "http://schemas.xmlsoap.org/soap/encoding/",
StopBody: StopBody{
XMLName: xml.Name{},
StopAction: StopAction{
XMLName: xml.Name{},
AVTransport: "urn:schemas-upnp-org:service:AVTransport:1",
InstanceID: "0",
Speed: "1",
},
},
}
xmlStart := []byte("<?xml version='1.0' encoding='utf-8'?>")
b, err := xml.Marshal(d)
if err != nil {
fmt.Println(err)
return make([]byte, 0), err
}

return append(xmlStart, b...), nil
}
40 changes: 24 additions & 16 deletions soapcalls/soapcallers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,8 @@ import (
"fmt"
"net/http"
"net/url"

"github.com/huin/goupnp/soap"
)

type playStopRequest struct {
InstanceID string
Speed string
}

type playStopResponse struct {
}

// TVPayload - we need this populated in order
type TVPayload struct {
TransportURL string
Expand Down Expand Up @@ -54,18 +44,36 @@ func setAVTransportSoapCall(videoURL, subtitleURL, transporturl string) error {

// PlayStopSoapCall - Build and call the play soap call
func playStopSoapCall(action, transporturl string) error {
parsedURLtransport, err := url.Parse(transporturl)
if err != nil {
return err
}

psRequest := &playStopRequest{InstanceID: "0", Speed: "1"}
psResponse := &playStopResponse{}
var xml []byte
if action == "Play" {
xml, err = playSoapBuild()
}

parsedURL, err := url.Parse(transporturl)
if action == "Stop" {
xml, err = stopSoapBuild()
}

client := &http.Client{}
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xml))
if err != nil {
return err
}

newPlaycall := soap.NewSOAPClient(*parsedURL)
if err := newPlaycall.PerformAction("urn:schemas-upnp-org:service:AVTransport:1",
action, psRequest, psResponse); err != nil {
headers := http.Header{
"SOAPAction": []string{`"urn:schemas-upnp-org:service:AVTransport:1#` + action + `"`},
"content-type": []string{"text/xml"},
"charset": []string{"utf-8"},
"Connection": []string{"close"},
}
req.Header = headers

_, err = client.Do(req)
if err != nil {
return err
}
return nil
Expand Down

0 comments on commit 0bef5b3

Please sign in to comment.