diff --git a/server/dlna/list.go b/server/dlna/list.go index c15c70f..2debb0a 100644 --- a/server/dlna/list.go +++ b/server/dlna/list.go @@ -9,14 +9,12 @@ import ( "time" "github.com/anacrolix/dms/dlna" - "github.com/anacrolix/dms/dlna/dms" "github.com/anacrolix/dms/upnpav" "server/log" "server/settings" "server/torr" "server/torr/state" - "server/utils" ) func getTorrents() (ret []interface{}) { @@ -122,18 +120,14 @@ func getLink(host, path string) string { } func getObjFromTorrent(path, parent, host string, torr *torr.Torrent, file *state.TorrentFileStat) (ret interface{}) { - // only playable files - if utils.GetMimeType(file.Path) == "*/*" { + + mime, err := MimeTypeByPath(file.Path) + if err != nil { + log.TLogln("Can't detect mime type", err) return } - mime, err := dms.MimeTypeByPath(file.Path) - if err != nil { - //return // this always err - if utils.GetMimeType(file.Path) == "video/*" { - mime = "video/mpeg" - } else { - mime = "audio/mpeg" - } + if !mime.IsMedia() { + return } obj := upnpav.Object{ diff --git a/server/dlna/mimetype.go b/server/dlna/mimetype.go new file mode 100644 index 0000000..ce494a6 --- /dev/null +++ b/server/dlna/mimetype.go @@ -0,0 +1,123 @@ +package dlna + +import ( + "log" + "mime" + "net/http" + "os" + "path" + "strings" + +) + +func init() { + +// Add a minimal number of mime types to augment go's built in types +// for environments which don't have access to a mime.types file (e.g. +// Termux on android) + for _, t := range []struct { + mimeType string + extensions string + }{ + {"audio/flac", ".flac"}, + {"audio/mpeg", ".mpga,.mpega,.mp2,.mp3,.m4a"}, + {"audio/ogg", ".oga,.ogg,.opus,.spx"}, + {"audio/x-wav", ".wav"}, + {"image/tiff", ".tiff,.tif"}, + {"video/dv", ".dif,.dv"}, + {"video/fli", ".fli"}, + {"video/mpeg", ".mpeg,.mpg,.mpe"}, + {"video/MP2T", ".ts"}, + {"video/mp4", ".mp4"}, + {"video/quicktime", ".qt,.mov"}, + {"video/ogg", ".ogv"}, + {"video/webm", ".webm"}, + {"video/x-msvideo", ".avi"}, + {"video/x-matroska", ".mpv,.mkv"}, + {"text/srt", ".srt"}, + } { + for _, ext := range strings.Split(t.extensions, ",") { + err := mime.AddExtensionType(ext, t.mimeType) + if err != nil { + panic(err) + } + } + } + if err := mime.AddExtensionType(".rmvb", "application/vnd.rn-realmedia-vbr"); err != nil { + log.Printf("Could not register application/vnd.rn-realmedia-vbr MIME type: %s", err) + } + if err := mime.AddExtensionType(".ogv", "video/ogg"); err != nil { + log.Printf("Could not register video/ogg MIME type: %s", err) + } +} + +// Example: "video/mpeg" +type mimeType string + +// IsMedia returns true for media MIME-types +func (mt mimeType) IsMedia() bool { + return mt.IsVideo() || mt.IsAudio() || mt.IsImage() +} + +// IsVideo returns true for video MIME-types +func (mt mimeType) IsVideo() bool { + return strings.HasPrefix(string(mt), "video/") || mt == "application/vnd.rn-realmedia-vbr" +} + +// IsAudio returns true for audio MIME-types +func (mt mimeType) IsAudio() bool { + return strings.HasPrefix(string(mt), "audio/") +} + +// IsImage returns true for image MIME-types +func (mt mimeType) IsImage() bool { + return strings.HasPrefix(string(mt), "image/") +} + +// Returns the group "type", the part before the '/'. +func (mt mimeType) Type() string { + return strings.SplitN(string(mt), "/", 2)[0] +} + +// Returns the string representation of this MIME-type +func (mt mimeType) String() string { + return string(mt) +} + +// MimeTypeByPath determines the MIME-type of file at the given path +func MimeTypeByPath(filePath string) (ret mimeType, err error) { + ret = mimeTypeByBaseName(path.Base(filePath)) + if ret == "" { + ret, err = mimeTypeByContent(filePath) + } + if ret == "video/x-msvideo" { + ret = "video/avi" + } else if ret == "" { + ret = "application/octet-stream" + } + return +} + +// Guess MIME-type from the extension, ignoring ".part". +func mimeTypeByBaseName(name string) mimeType { + name = strings.TrimSuffix(name, ".part") + ext := path.Ext(name) + if ext != "" { + return mimeType(mime.TypeByExtension(ext)) + } + return mimeType("") +} + +// Guess the MIME-type by analysing the first 512 bytes of the file. +func mimeTypeByContent(path string) (ret mimeType, err error) { + file, err := os.Open(path) + if err != nil { + return + } + defer file.Close() + var data [512]byte + if n, err := file.Read(data[:]); err == nil { + ret = mimeType(http.DetectContentType(data[:n])) + } + return +}