Add context to the soapcalls API

This commit is contained in:
Alex Ballas
2023-05-23 19:44:51 +03:00
parent d8eec476da
commit 4e5131149e
10 changed files with 40 additions and 26 deletions

View File

@@ -147,7 +147,7 @@ func run() error {
scr := &dummyScreen{ctxCancel: cancel} scr := &dummyScreen{ctxCancel: cancel}
tvdata, err := soapcalls.NewTVPayload(soapcalls.Options{ tvdata, err := soapcalls.NewTVPayload(&soapcalls.Options{
DMR: flagRes.dmrURL, DMR: flagRes.dmrURL,
Media: absMediaFile, Media: absMediaFile,
Subs: absSubtitlesFile, Subs: absSubtitlesFile,

View File

@@ -147,7 +147,7 @@ func run() error {
return err return err
} }
tvdata, err := soapcalls.NewTVPayload(soapcalls.Options{ tvdata, err := soapcalls.NewTVPayload(&soapcalls.Options{
DMR: flagRes.dmrURL, DMR: flagRes.dmrURL,
Media: absMediaFile, Media: absMediaFile,
Subs: absSubtitlesFile, Subs: absSubtitlesFile,

View File

@@ -1,6 +1,7 @@
package devices package devices
import ( import (
"context"
"fmt" "fmt"
"sort" "sort"
@@ -30,7 +31,7 @@ func LoadSSDPservices(delay int) (map[string]string, error) {
// (stop,play,pause). If we need support other functionalities // (stop,play,pause). If we need support other functionalities
// like volume control we need to use the RenderingControl service. // like volume control we need to use the RenderingControl service.
if srv.Type == "urn:schemas-upnp-org:service:AVTransport:1" { if srv.Type == "urn:schemas-upnp-org:service:AVTransport:1" {
friendlyName, err := soapcalls.GetFriendlyName(srv.Location) friendlyName, err := soapcalls.GetFriendlyName(context.Background(), srv.Location)
if err != nil { if err != nil {
continue continue
} }

View File

@@ -4,6 +4,7 @@
package gui package gui
import ( import (
"context"
"errors" "errors"
"log" "log"
"math" "math"
@@ -382,7 +383,7 @@ func mainWindow(s *NewScreen) fyne.CanvasObject {
// Widgets actions // Widgets actions
list.OnSelected = func(id widget.ListItemID) { list.OnSelected = func(id widget.ListItemID) {
playpause.Enable() playpause.Enable()
t, err := soapcalls.DMRextractor(data[id].addr) t, err := soapcalls.DMRextractor(context.Background(), data[id].addr)
check(s, err) check(s, err)
if err == nil { if err == nil {
s.selectedDevice = data[id] s.selectedDevice = data[id]

View File

@@ -1,15 +1,16 @@
package soapcalls package soapcalls
import ( import (
"context"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"net/http" "net/http"
) )
// GetFriendlyName returns the friendly name value for a the specific DMR url. // GetFriendlyName returns the friendly name value for a the specific DMR url.
func GetFriendlyName(dmr string) (string, error) { func GetFriendlyName(ctx context.Context, dmr string) (string, error) {
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, dmr, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, dmr, nil)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to create NewRequest for GetFriendlyName: %w", err) return "", fmt.Errorf("failed to create NewRequest for GetFriendlyName: %w", err)
} }

View File

@@ -1,6 +1,7 @@
package soapcalls package soapcalls
import ( import (
"context"
"encoding/xml" "encoding/xml"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@@ -31,7 +32,7 @@ func TestGetFriendlyName(t *testing.T) {
defer testServer.Close() defer testServer.Close()
friendly, err := GetFriendlyName(testServer.URL) friendly, err := GetFriendlyName(context.Background(), testServer.URL)
if err != nil { if err != nil {
t.Fatalf("%s: Failed to call GetFriendlyName due to %s", testName, err.Error()) t.Fatalf("%s: Failed to call GetFriendlyName due to %s", testName, err.Error())
} }

View File

@@ -2,6 +2,7 @@ package soapcalls
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
@@ -37,6 +38,7 @@ type TVPayload struct {
initLogOnce sync.Once initLogOnce sync.Once
mu sync.RWMutex mu sync.RWMutex
Logging io.Writer Logging io.Writer
ctx context.Context
MediaRenderersStates map[string]*States MediaRenderersStates map[string]*States
CurrentTimers map[string]*time.Timer CurrentTimers map[string]*time.Timer
InitialMediaRenderersStates map[string]bool InitialMediaRenderersStates map[string]bool
@@ -179,7 +181,7 @@ func (p *TVPayload) setAVTransportSoapCall() error {
retryClient.Logger = nil retryClient.Logger = nil
client := retryClient.StandardClient() client := retryClient.StandardClient()
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xml)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xml))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "setAVTransportSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "setAVTransportSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("setAVTransportSoapCall POST error: %w", err) return fmt.Errorf("setAVTransportSoapCall POST error: %w", err)
@@ -245,7 +247,7 @@ func (p *TVPayload) setNextAVTransportSoapCall(clear bool) error {
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xml)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xml))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "setNextAVTransportSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "setNextAVTransportSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("setNextAVTransportSoapCall POST error: %w", err) return fmt.Errorf("setNextAVTransportSoapCall POST error: %w", err)
@@ -330,7 +332,7 @@ func (p *TVPayload) PlayPauseStopSoapCall(action string) error {
client = retryClient.StandardClient() client = retryClient.StandardClient()
} }
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xml)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xml))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "AVTransportActionSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "AVTransportActionSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("AVTransportActionSoapCall POST error: %w", err) return fmt.Errorf("AVTransportActionSoapCall POST error: %w", err)
@@ -407,7 +409,7 @@ func (p *TVPayload) SeekSoapCall(reltime string) error {
client = retryClient.StandardClient() client = retryClient.StandardClient()
} }
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xml)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xml))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "SeekSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "SeekSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("SeekSoapCall POST error: %w", err) return fmt.Errorf("SeekSoapCall POST error: %w", err)
@@ -481,7 +483,7 @@ func (p *TVPayload) SubscribeSoapCall(uuidInput string) error {
client := retryClient.StandardClient() client := retryClient.StandardClient()
req, err := http.NewRequest("SUBSCRIBE", parsedURLcontrol.String(), nil) req, err := http.NewRequestWithContext(p.ctx, "SUBSCRIBE", parsedURLcontrol.String(), nil)
if err != nil { if err != nil {
p.Log().Error().Str("Method", "SubscribeSoapCall").Str("Action", "Prepare SUBSCRIBE").Err(err).Msg("") p.Log().Error().Str("Method", "SubscribeSoapCall").Str("Action", "Prepare SUBSCRIBE").Err(err).Msg("")
return fmt.Errorf("SubscribeSoapCall SUBSCRIBE error: %w", err) return fmt.Errorf("SubscribeSoapCall SUBSCRIBE error: %w", err)
@@ -592,7 +594,7 @@ func (p *TVPayload) UnsubscribeSoapCall(uuid string) error {
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("UNSUBSCRIBE", parsedURLcontrol.String(), nil) req, err := http.NewRequestWithContext(p.ctx, "UNSUBSCRIBE", parsedURLcontrol.String(), nil)
if err != nil { if err != nil {
return fmt.Errorf("UnsubscribeSoapCall UNSUBSCRIBE error: %w", err) return fmt.Errorf("UnsubscribeSoapCall UNSUBSCRIBE error: %w", err)
} }
@@ -654,7 +656,7 @@ func (p *TVPayload) GetMuteSoapCall() (string, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "GetMuteSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "GetMuteSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return "", fmt.Errorf("GetMuteSoapCall POST error: %w", err) return "", fmt.Errorf("GetMuteSoapCall POST error: %w", err)
@@ -731,7 +733,7 @@ func (p *TVPayload) SetMuteSoapCall(number string) error {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "SetMuteSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "SetMuteSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("SetMuteSoapCall POST error: %w", err) return fmt.Errorf("SetMuteSoapCall POST error: %w", err)
@@ -798,7 +800,7 @@ func (p *TVPayload) GetVolumeSoapCall() (int, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "GetVolumeSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "GetVolumeSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return 0, fmt.Errorf("GetVolumeSoapCall POST error: %w", err) return 0, fmt.Errorf("GetVolumeSoapCall POST error: %w", err)
@@ -886,7 +888,7 @@ func (p *TVPayload) SetVolumeSoapCall(v string) error {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedRenderingControlURL.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "SetVolumeSoapCall").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "SetVolumeSoapCall").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("SetVolumeSoapCall POST error: %w", err) return fmt.Errorf("SetVolumeSoapCall POST error: %w", err)
@@ -953,7 +955,7 @@ func (p *TVPayload) GetProtocolInfo() error {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedConnectionManagerURL.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedConnectionManagerURL.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "GetProtocolInfo").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "GetProtocolInfo").Str("Action", "Prepare POST").Err(err).Msg("")
return fmt.Errorf("GetProtocolInfo POST error: %w", err) return fmt.Errorf("GetProtocolInfo POST error: %w", err)
@@ -1027,7 +1029,7 @@ func (p *TVPayload) Gapless() (string, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "Gapless").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "Gapless").Str("Action", "Prepare POST").Err(err).Msg("")
return "", fmt.Errorf("Gapless POST error: %w", err) return "", fmt.Errorf("Gapless POST error: %w", err)
@@ -1106,7 +1108,7 @@ func (p *TVPayload) GetTransportInfo() ([]string, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "GetTransportInfo").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "GetTransportInfo").Str("Action", "Prepare POST").Err(err).Msg("")
return nil, fmt.Errorf("GetTransportInfo POST error: %w", err) return nil, fmt.Errorf("GetTransportInfo POST error: %w", err)
@@ -1188,7 +1190,7 @@ func (p *TVPayload) GetPositionInfo() ([]string, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder)) req, err := http.NewRequestWithContext(p.ctx, "POST", parsedURLtransport.String(), bytes.NewReader(xmlbuilder))
if err != nil { if err != nil {
p.Log().Error().Str("Method", "GetPositionInfo").Str("Action", "Prepare POST").Err(err).Msg("") p.Log().Error().Str("Method", "GetPositionInfo").Str("Action", "Prepare POST").Err(err).Msg("")
return nil, fmt.Errorf("GetPositionInfo POST error: %w", err) return nil, fmt.Errorf("GetPositionInfo POST error: %w", err)

View File

@@ -1,6 +1,7 @@
package soapcalls package soapcalls
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"time" "time"
@@ -10,6 +11,7 @@ import (
type Options struct { type Options struct {
Logging io.Writer Logging io.Writer
ctx context.Context
DMR string DMR string
Media string Media string
Subs string Subs string
@@ -19,8 +21,12 @@ type Options struct {
Seek bool Seek bool
} }
func NewTVPayload(o Options) (*TVPayload, error) { func NewTVPayload(o *Options) (*TVPayload, error) {
upnpServicesURLs, err := DMRextractor(o.DMR) if o.ctx == nil {
o.ctx = context.Background()
}
upnpServicesURLs, err := DMRextractor(o.ctx, o.DMR)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package soapcalls package soapcalls
import ( import (
"context"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io"
@@ -55,7 +56,7 @@ type DMRextracted struct {
} }
// DMRextractor extracts the services URLs from the main DMR xml. // DMRextractor extracts the services URLs from the main DMR xml.
func DMRextractor(dmrurl string) (*DMRextracted, error) { func DMRextractor(ctx context.Context, dmrurl string) (*DMRextracted, error) {
var root rootNode var root rootNode
ex := &DMRextracted{} ex := &DMRextracted{}
@@ -65,7 +66,7 @@ func DMRextractor(dmrurl string) (*DMRextracted, error) {
} }
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest("GET", dmrurl, nil) req, err := http.NewRequestWithContext(ctx, "GET", dmrurl, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("DMRextractor GET error: %w", err) return nil, fmt.Errorf("DMRextractor GET error: %w", err)
} }

View File

@@ -1,6 +1,7 @@
package soapcalls package soapcalls
import ( import (
"context"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@@ -42,7 +43,7 @@ func TestDMRextractor(t *testing.T) {
defer testServer.Close() defer testServer.Close()
_, err := DMRextractor(testServer.URL) _, err := DMRextractor(context.Background(), testServer.URL)
if err != nil { if err != nil {
t.Fatalf("Failed to call DMRextractor due to %s", err.Error()) t.Fatalf("Failed to call DMRextractor due to %s", err.Error())
} }