From c86a186e038913018e56281509054284a2e0eb99 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Fri, 3 Sep 2021 23:22:40 +0300 Subject: [PATCH 1/8] remove reader lock and wait pieceComplete --- server/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/go.mod b/server/go.mod index 910fe22..48faac2 100644 --- a/server/go.mod +++ b/server/go.mod @@ -4,7 +4,7 @@ go 1.17 replace ( github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210902055723-0fcf49216c68 - github.com/anacrolix/torrent v1.30.3 => github.com/tsynik/torrent v1.2.7-0.20210825105145-c21425452ac8 + github.com/anacrolix/torrent v1.30.3 => github.com/tsynik/torrent v1.2.7-0.20210903201852-d16ba45e0bbd ) exclude github.com/willf/bitset v1.2.0 From 66d3e6402fc2cc27ca3b548aa097f938a758d57a Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Mon, 6 Sep 2021 03:36:08 +0300 Subject: [PATCH 2/8] update dlna --- server/dlna/dlna.go | 3 +++ server/dlna/list.go | 41 ++++++++++++++++++++++++++++++++++++++--- server/dlna/mimetype.go | 35 ++++++++++++++++++++++++----------- server/go.mod | 2 +- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/server/dlna/dlna.go b/server/dlna/dlna.go index 6916dfd..b4bd600 100644 --- a/server/dlna/dlna.go +++ b/server/dlna/dlna.go @@ -90,6 +90,9 @@ func Stop() { func onBrowse(path, rootObjectPath, host, userAgent string) (ret []interface{}, err error) { if path == "/" { + ret = getRoot() + return + } else if path == "/Torrents" { ret = getTorrents() return } else if isHashPath(path) { diff --git a/server/dlna/list.go b/server/dlna/list.go index aff56a0..7942183 100644 --- a/server/dlna/list.go +++ b/server/dlna/list.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "path/filepath" + "sort" "strconv" "strings" "time" @@ -17,14 +18,41 @@ import ( "server/torr/state" ) +func getRoot() (ret []interface{}) { + + // Root Object + rootObj := upnpav.Object{ + ID: "%2FTorrents", + ParentID: "0", + Title: "Torrents", + Class: "object.container.storageFolder", + Restricted: 1, + Date: upnpav.Timestamp{Time: time.Now()}, + } + + // add Root Object + len := len(torr.ListTorrent()) + cnt := upnpav.Container{Object: rootObj, ChildCount: len} + ret = append(ret, cnt) + + return + +} + func getTorrents() (ret []interface{}) { + torrs := torr.ListTorrent() + // sort by title as in cds SortCaps + sort.Slice(torrs, func(i, j int) bool { + return torrs[i].Title < torrs[j].Title + }) + var vol = 0 for _, t := range torrs { vol++ obj := upnpav.Object{ ID: "%2F" + t.TorrentSpec.InfoHash.HexString(), - ParentID: "0", + ParentID: "%2FTorrents", Title: t.Title, Class: "object.container.storageFolder", Restricted: 1, @@ -38,7 +66,7 @@ func getTorrents() (ret []interface{}) { if vol == 0 { obj := upnpav.Object{ ID: "%2FNo Torrents", - ParentID: "0", + ParentID: "%2FTorrents", Title: "No Torrents", Class: "object.container.storageFolder", Restricted: 1, @@ -46,6 +74,7 @@ func getTorrents() (ret []interface{}) { } cnt := upnpav.Container{Object: obj, ChildCount: 1} ret = append(ret, cnt) + vol = 1 } return } @@ -139,12 +168,17 @@ func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *stat mime, err := MimeTypeByPath(file.Path) if err != nil { - log.TLogln("Can't detect mime type", err) + if settings.BTsets.EnableDebug { + log.TLogln("Can't detect mime type", err) + } return } if !mime.IsMedia() { return } + if settings.BTsets.EnableDebug { + log.TLogln("mime type", mime.String(), file.Path) + } obj := upnpav.Object{ ID: parent + "%2F" + file.Path, @@ -163,6 +197,7 @@ func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *stat item.Res = append(item.Res, upnpav.Resource{ URL: getLink(host, pathPlay), ProtocolInfo: fmt.Sprintf("http-get:*:%s:%s", mime, dlna.ContentFeatures{ + SupportTimeSeek: true, SupportRange: true, }.String()), Size: uint64(file.Length), diff --git a/server/dlna/mimetype.go b/server/dlna/mimetype.go index 4f5a8f3..b60fb72 100644 --- a/server/dlna/mimetype.go +++ b/server/dlna/mimetype.go @@ -19,29 +19,31 @@ func init() { mimeType string extensions string }{ - {"audio/aac", ".aac"}, + {"image/bmp", ".bmp"}, + {"image/gif", ".gif"}, + {"image/jpeg", ".jpg,.jpeg"}, + {"image/png", ".png"}, + {"image/tiff", ".tiff,.tif"}, + {"audio/x-aac", ".aac"}, {"audio/flac", ".flac"}, {"audio/mpeg", ".mpga,.mpega,.mp2,.mp3,.m4a"}, {"audio/ogg", ".oga,.ogg,.opus,.spx"}, {"audio/opus", ".opus"}, {"audio/weba", ".weba"}, {"audio/x-wav", ".wav"}, - {"image/bmp", ".bmp"}, - {"image/gif", ".gif"}, - {"image/jpeg", ".jpg,.jpeg"}, - {"image/png", ".png"}, - {"image/tiff", ".tiff,.tif"}, {"video/dv", ".dif,.dv"}, {"video/fli", ".fli"}, - {"video/mpeg", ".mpeg,.mpg,.mpe"}, - {"video/mp2t", ".ts,.m2ts,.mts"}, {"video/mp4", ".mp4"}, - {"video/quicktime", ".qt,.mov"}, + {"video/mpeg", ".mpeg,.mpg,.mpe"}, + {"video/x-matroska", ".mpv,.mkv"}, + {"video/mp2t", ".ts,.m2ts,.mts"}, {"video/ogg", ".ogv"}, {"video/webm", ".webm"}, {"video/x-msvideo", ".avi"}, - {"video/x-matroska", ".mpv,.mkv"}, + {"video/x-quicktime", ".qt,.mov"}, {"text/srt", ".srt"}, + {"text/smi", ".smi"}, + {"text/ssa", ".ssa"}, } { for _, ext := range strings.Split(t.extensions, ",") { err := mime.AddExtensionType(ext, t.mimeType) @@ -78,6 +80,11 @@ func (mt mimeType) IsImage() bool { return strings.HasPrefix(string(mt), "image/") } +// IsSub returns true for subtitles MIME-types +func (mt mimeType) IsSub() bool { + return strings.HasPrefix(string(mt), "text/srt") || strings.HasPrefix(string(mt), "text/smi") || strings.HasPrefix(string(mt), "text/ssa") +} + // Returns the group "type", the part before the '/'. func (mt mimeType) Type() string { return strings.SplitN(string(mt), "/", 2)[0] @@ -94,7 +101,13 @@ func MimeTypeByPath(filePath string) (ret mimeType, err error) { if ret == "" { ret, err = mimeTypeByContent(filePath) } - if ret == "video/x-msvideo" { +// Custom DLNA-compat mime mappings +// TODO: make this client headers / profile map + if ret == "video/mp2t" { + ret = "video/mpeg" + else if ret == "video/x-matroska" { + ret = "video/mpeg" + else if ret == "video/x-msvideo" { ret = "video/avi" } else if ret == "" { ret = "application/octet-stream" diff --git a/server/go.mod b/server/go.mod index 48faac2..fb2500e 100644 --- a/server/go.mod +++ b/server/go.mod @@ -3,7 +3,7 @@ module server go 1.17 replace ( - github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210902055723-0fcf49216c68 + github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210906003125-e00296ccb6ef github.com/anacrolix/torrent v1.30.3 => github.com/tsynik/torrent v1.2.7-0.20210903201852-d16ba45e0bbd ) From afa4a3d3038135fe7c64fa86965acbd6f4edc45b Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Mon, 6 Sep 2021 03:44:03 +0300 Subject: [PATCH 3/8] typos --- server/dlna/mimetype.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/dlna/mimetype.go b/server/dlna/mimetype.go index b60fb72..a46e9aa 100644 --- a/server/dlna/mimetype.go +++ b/server/dlna/mimetype.go @@ -105,9 +105,9 @@ func MimeTypeByPath(filePath string) (ret mimeType, err error) { // TODO: make this client headers / profile map if ret == "video/mp2t" { ret = "video/mpeg" - else if ret == "video/x-matroska" { + } else if ret == "video/x-matroska" { ret = "video/mpeg" - else if ret == "video/x-msvideo" { + } else if ret == "video/x-msvideo" { ret = "video/avi" } else if ret == "" { ret = "application/octet-stream" From 6d499aa655409301b1e05885b0a47dfd829c5e94 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Mon, 6 Sep 2021 08:52:26 +0300 Subject: [PATCH 4/8] disable win sleep --- server/cmd/preconfig_win.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/server/cmd/preconfig_win.go b/server/cmd/preconfig_win.go index 1a642f5..1d168f3 100644 --- a/server/cmd/preconfig_win.go +++ b/server/cmd/preconfig_win.go @@ -1,7 +1,28 @@ +//go:build windows // +build windows package main -func Preconfig(kill bool) { +import ( + "time" +) +const ( + EsSystemRequired = 0x00000001 + EsContinuous = 0x80000000 +) + +var pulseTime = 1 * time.Minute + +func Preconfig(kill bool) { + // don't sleep/hibernate windows + kernel32 := syscall.NewLazyDLL("kernel32.dll") + setThreadExecStateProc := kernel32.NewProc("SetThreadExecutionState") + pulse := time.NewTicker(pulseTime) + for { + select { + case <-pulse.C: + setThreadExecStateProc.Call(uintptr(EsSystemRequired)) + } + } } From 4d22d8f13192d55d3a06feec3df6f1f153b97366 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Tue, 7 Sep 2021 10:34:28 +0300 Subject: [PATCH 5/8] fix DLNA IDs --- server/dlna/dlna.go | 4 ++-- server/dlna/list.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/server/dlna/dlna.go b/server/dlna/dlna.go index b4bd600..062d82c 100644 --- a/server/dlna/dlna.go +++ b/server/dlna/dlna.go @@ -92,13 +92,13 @@ func onBrowse(path, rootObjectPath, host, userAgent string) (ret []interface{}, if path == "/" { ret = getRoot() return - } else if path == "/Torrents" { + } else if path == "/TR" { ret = getTorrents() return } else if isHashPath(path) { ret = getTorrent(path, host) return - } else if filepath.Base(path) == "Load Torrent" { + } else if filepath.Base(path) == "LD" { ret = loadTorrent(path, host) } return diff --git a/server/dlna/list.go b/server/dlna/list.go index 7942183..23bf9cd 100644 --- a/server/dlna/list.go +++ b/server/dlna/list.go @@ -22,7 +22,7 @@ func getRoot() (ret []interface{}) { // Root Object rootObj := upnpav.Object{ - ID: "%2FTorrents", + ID: "%2FTR", ParentID: "0", Title: "Torrents", Class: "object.container.storageFolder", @@ -52,7 +52,7 @@ func getTorrents() (ret []interface{}) { vol++ obj := upnpav.Object{ ID: "%2F" + t.TorrentSpec.InfoHash.HexString(), - ParentID: "%2FTorrents", + ParentID: "%2FTR", Title: t.Title, Class: "object.container.storageFolder", Restricted: 1, @@ -65,8 +65,8 @@ func getTorrents() (ret []interface{}) { } if vol == 0 { obj := upnpav.Object{ - ID: "%2FNo Torrents", - ParentID: "%2FTorrents", + ID: "%2FNT", + ParentID: "%2FTR", Title: "No Torrents", Class: "object.container.storageFolder", Restricted: 1, @@ -98,7 +98,7 @@ func getTorrent(path, host string) (ret []interface{}) { // if torrent not loaded, get button for load if torr.Files() == nil { obj := upnpav.Object{ - ID: parent + "%2FLoad Torrent", + ID: parent + "%2FLD", ParentID: parent, Title: "Load Torrent", Class: "object.container.storageFolder", @@ -181,7 +181,7 @@ func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *stat } obj := upnpav.Object{ - ID: parent + "%2F" + file.Path, + ID: url.PathEscape(parent + "/" + file.Path), ParentID: parent, Title: file.Path, Class: "object.item." + mime.Type() + "Item", From 23a00b29de643d1ca7269e5f67998dc6486f4c23 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Tue, 7 Sep 2021 22:32:22 +0300 Subject: [PATCH 6/8] Update list.go --- server/dlna/list.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/dlna/list.go b/server/dlna/list.go index 23bf9cd..04ae2d4 100644 --- a/server/dlna/list.go +++ b/server/dlna/list.go @@ -173,6 +173,7 @@ func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *stat } return } + // TODO: handle subtitles for media if !mime.IsMedia() { return } @@ -181,7 +182,7 @@ func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *stat } obj := upnpav.Object{ - ID: url.PathEscape(parent + "/" + file.Path), + ID: parent + "%2F" + url.PathEscape(file.Path), ParentID: parent, Title: file.Path, Class: "object.item." + mime.Type() + "Item", From 813426a1bf8de808710888ac8fb5158a170e1603 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Tue, 7 Sep 2021 22:36:26 +0300 Subject: [PATCH 7/8] update torrent / dms short scpds and cp1251 filenames fix --- server/go.mod | 5 +++-- server/go.sum | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/server/go.mod b/server/go.mod index fb2500e..c5cc338 100644 --- a/server/go.mod +++ b/server/go.mod @@ -3,8 +3,8 @@ module server go 1.17 replace ( - github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210906003125-e00296ccb6ef - github.com/anacrolix/torrent v1.30.3 => github.com/tsynik/torrent v1.2.7-0.20210903201852-d16ba45e0bbd + github.com/anacrolix/dms v1.2.2 => github.com/tsynik/dms v0.0.0-20210906013928-2decf97d15be + github.com/anacrolix/torrent v1.30.3 => github.com/tsynik/torrent v1.2.7-0.20210907192509-2141ede9aa09 ) exclude github.com/willf/bitset v1.2.0 @@ -67,6 +67,7 @@ require ( golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + golang.org/x/text v0.3.6 // indirect google.golang.org/protobuf v1.25.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/server/go.sum b/server/go.sum index b5e40d3..6a19808 100644 --- a/server/go.sum +++ b/server/go.sum @@ -659,10 +659,10 @@ github.com/tinylib/msgp v1.1.1/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tsynik/dms v0.0.0-20210902055723-0fcf49216c68 h1:Pzqhxa0KgN6DVHCmLqzkyp9qlA6RKft9LY2Mj1+Ykgg= -github.com/tsynik/dms v0.0.0-20210902055723-0fcf49216c68/go.mod h1:1GqMUla/yTV3GFjpKMpmdntkTl6aslGK3jfIksEwIdI= -github.com/tsynik/torrent v1.2.7-0.20210825105145-c21425452ac8 h1:LHF4YkeJ2dg/Mc/IWW0I6SX7Zq/oyDOG9PlQnaSF1Ns= -github.com/tsynik/torrent v1.2.7-0.20210825105145-c21425452ac8/go.mod h1:E9gvoHzc58EtTudJbzZ2Ho7SKDCYk84734hB9ztBJS4= +github.com/tsynik/dms v0.0.0-20210906013928-2decf97d15be h1:QGjo6yqsZmgjXc0bPg1eJSdFTpZxTtW9M4cmYUyklL4= +github.com/tsynik/dms v0.0.0-20210906013928-2decf97d15be/go.mod h1:1GqMUla/yTV3GFjpKMpmdntkTl6aslGK3jfIksEwIdI= +github.com/tsynik/torrent v1.2.7-0.20210907192509-2141ede9aa09 h1:GHhNKxddZiYrWeiXqMQiPKcSIXKF+o/w1wrqHOgOFrk= +github.com/tsynik/torrent v1.2.7-0.20210907192509-2141ede9aa09/go.mod h1:E9gvoHzc58EtTudJbzZ2Ho7SKDCYk84734hB9ztBJS4= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= @@ -854,6 +854,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From a8c05b88a45e003c42d2ef89f6f7d27837e3074a Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Tue, 7 Sep 2021 22:56:51 +0300 Subject: [PATCH 8/8] fix windows builds --- server/cmd/preconfig_win.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/cmd/preconfig_win.go b/server/cmd/preconfig_win.go index 1d168f3..0e1fc20 100644 --- a/server/cmd/preconfig_win.go +++ b/server/cmd/preconfig_win.go @@ -4,6 +4,7 @@ package main import ( + "syscall" "time" )