diff --git a/dlna/contenddirectoryservice.go b/dlna/contenddirectoryservice.go index a430c2d59..8ffe7e225 100644 --- a/dlna/contenddirectoryservice.go +++ b/dlna/contenddirectoryservice.go @@ -11,6 +11,7 @@ import ( "os" "path" "path/filepath" + "strings" "time" "github.com/anacrolix/dms/dlna" @@ -77,6 +78,7 @@ func (cds *contentDirectoryService) cdsObjectToUpnpavObject(cdsObject object, is // Returns all the upnpav objects in a directory. func (cds *contentDirectoryService) readContainer(o object, host string) (ret []interface{}, err error) { log.Printf("ReadContainer called with : %+v", o) + //TODO implement HTTP routing in a way that isn't awful switch o.Path { case "/": newObject := object{Path: "/Music"} @@ -109,6 +111,19 @@ func (cds *contentDirectoryService) readContainer(o object, host string) (ret [] case "/Music/Albums": } + + if strings.HasPrefix(o.Path, "/Music/Files/") { + libraryPath,_ := strings.CutPrefix(o.Path, "/Music/Files") + log.Printf("library path: %s", libraryPath) + files, _ := os.ReadDir(path.Join(conf.Server.MusicFolder, libraryPath)) + for _, file := range files { + child := object{ + path.Join(o.Path, file.Name()), + } + convObj, _ := cds.cdsObjectToUpnpavObject(child, file.IsDir(), host) + ret = append(ret, convObj) + } + } return } @@ -140,7 +155,7 @@ func (cds *contentDirectoryService) objectFromID(id string) (o object, err error func (cds *contentDirectoryService) Handle(action string, argsXML []byte, r *http.Request) (map[string]string, error) { host := r.Host - + log.Printf("Handle called with action: %s", action) switch action { case "GetSystemUpdateID": return map[string]string{ diff --git a/dlna/dlnaserver.go b/dlna/dlnaserver.go index 485f13f29..80746e77a 100644 --- a/dlna/dlnaserver.go +++ b/dlna/dlnaserver.go @@ -12,6 +12,8 @@ import ( "net" "net/http" "net/url" + "os" + "path" "strconv" "strings" "text/template" @@ -21,6 +23,7 @@ import ( "github.com/anacrolix/dms/soap" "github.com/anacrolix/dms/ssdp" "github.com/anacrolix/dms/upnp" + "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/server/events" ) @@ -264,9 +267,19 @@ func isAppropriatelyConfigured(intf net.Interface) bool { //handler for all paths under `/r` func (s *SSDPServer) resourceHandler(w http.ResponseWriter, r *http.Request) { - //remotePath := r.URL.Path + remotePath := r.URL.Path - w.Header().Set("Content-Length", strconv.FormatInt(1024, 10)) //TODO + localFile,_ := strings.CutPrefix(remotePath,"Music/Files/") + localFilePath := path.Join(conf.Server.MusicFolder, localFile) + + log.Printf("resource handler Executed with remote path: %s, localpath: %s", remotePath, localFilePath) + + fileStats,err := os.Stat(localFilePath) + if err != nil { + http.NotFound(w,r) + return + } + w.Header().Set("Content-Length", strconv.FormatInt(fileStats.Size(), 10)) // add some DLNA specific headers if r.Header.Get("getContentFeatures.dlna.org") != "" { @@ -276,7 +289,15 @@ func (s *SSDPServer) resourceHandler(w http.ResponseWriter, r *http.Request) { } w.Header().Set("transferMode.dlna.org", "Streaming") - //http.ServeContent(w, r, remotePath, time.Now(), in) + os.Open(localFilePath) + fileHandle,err := os.Open(localFilePath) + if err != nil { + fmt.Printf("file streaming error: %+v\n", err) + return + } + defer fileHandle.Close() + + http.ServeContent(w, r, remotePath, time.Now(), fileHandle) } // returns /rootDesc.xml templated