diff --git a/src/fs/cache.go b/src/fs/cache.go index a38d205..e490097 100644 --- a/src/fs/cache.go +++ b/src/fs/cache.go @@ -2,6 +2,7 @@ package main import ( "github.com/disintegration/imaging" + "github.com/frolovo22/tag" "os" "path/filepath" "strings" @@ -33,6 +34,45 @@ func thumbnailer(imagePath string, savePath string) error { return nil } +func cacheMetadataPicture(path string, savePath string) error { + tags, err := tag.ReadFile(path) + if err != nil { + logging.Error("error opening file: %s", err.Error()) + return err + } + + picture, err := tags.GetPicture() + if err != nil { + logging.Error(`Error getting media picture: %s`, err.Error()) + return err + } + + if picture != nil { + // song.mp3 + fileName := filepath.Base(path) + index := strings.Index(fileName, ".") + // song_artwork.jpg + artworkName := fileName[:index] + "_artwork" + ".jpg" + savePath = filepath.Join(filepath.Dir(savePath), artworkName) + + if err = os.MkdirAll(filepath.Dir(savePath), os.ModePerm); err != nil { + logging.Error(`Error creating parent directory for file: "%s". Error is: "%s"`, savePath, err.Error()) + return err + } + + if err = imaging.Save(picture, savePath); err != nil { + logging.Error(`Error saving image thumbnail for file at location: "%s". Error is: "%s"`, savePath, err.Error()) + return err + } + logging.Info("Thumbnail image saved for file: %s", path) + return nil + } + + logging.Info("Thumbnail image not found for file: %s", path) + return nil +} + + func fillCache(root string) error { filepath.Walk(root, fillCacheWalkFunc) return nil @@ -59,6 +99,8 @@ func fillCacheWalkFunc(path string, info os.FileInfo, err error) error { contentType := getContentType(path) if strings.Contains(contentType, "image") { thumbnailer(path, thumbnailPath) + } else { + cacheMetadataPicture(path, thumbnailPath) } } } else { diff --git a/src/fs/metadata.go b/src/fs/metadata.go new file mode 100644 index 0000000..b376917 --- /dev/null +++ b/src/fs/metadata.go @@ -0,0 +1,52 @@ +package main + +import ( + "github.com/frolovo22/tag" +) + +type Metadata struct { + Tag string `json:"tag"` + Title string `json:"title"` + Album string `json:"album"` + Artist string `json:"artist"` + AlbumArtist string `json:"album_artist"` + Composer string `json:"composer"` + Genre string `json:"genre"` + Year int `json:"year"` + TrackNumber int `json:"track_number"` + AlbumArtwork string `json:"album_artwork"` +} + +func getMetaData(tags tag.Metadata) (*Metadata) { + + title, _ := tags.GetTitle() + album, _ := tags.GetAlbum() + tagVersion := tags.GetVersion() + artist, _ := tags.GetArtist() + albumArtist, _ := tags.GetAlbumArtist() + genre, _ := tags.GetGenre() + trackNumber, _, _ := tags.GetTrackNumber() + composer, _ := tags.GetComposer() + year, _ := tags.GetYear() + + metadata := &Metadata{ + Tag: tagVersion.String(), + Title: title, + Album: album, + Artist: artist, + AlbumArtist: albumArtist, + Composer: composer, + Genre: genre, + Year: year, + TrackNumber: trackNumber, + } + return metadata +} + +func getMetadataByPath(path string) (*Metadata, error) { + tags, err := tag.ReadFile(path) + if err != nil { + return nil, err + } + return getMetaData(tags), nil +} \ No newline at end of file diff --git a/src/fs/service.go b/src/fs/service.go index 08baa3c..d91ee08 100644 --- a/src/fs/service.go +++ b/src/fs/service.go @@ -13,6 +13,7 @@ import ( "bytes" "crypto/tls" "database/sql" + "encoding/json" "errors" "fmt" "github.com/amahi/go-metadata" @@ -76,6 +77,7 @@ func NewMercuryFSService(rootDir, localAddr string, isDemo bool) (service *Mercu apiRouter.HandleFunc("/files", use(service.deleteFile, service.shareWriteAccess, service.restrictCache)).Methods("DELETE") apiRouter.HandleFunc("/files", use(service.uploadFile, service.shareWriteAccess, service.restrictCache)).Methods("POST") apiRouter.HandleFunc("/cache", use(service.serveCache, service.shareReadAccess)).Methods("GET") + apiRouter.HandleFunc("/meta", use(service.serveMetadata, service.shareReadAccess, service.restrictCache)).Methods("GET") apiRouter.HandleFunc("/apps", service.appsList).Methods("GET") apiRouter.HandleFunc("/md", service.getMetadata).Methods("GET") apiRouter.HandleFunc("/hda_debug", service.hdaDebug).Methods("GET") @@ -745,6 +747,56 @@ func (service *MercuryFsService) uploadFile(writer http.ResponseWriter, request return } +func (service *MercuryFsService) serveMetadata(writer http.ResponseWriter, request *http.Request) { + q := request.URL + path := q.Query().Get("p") + share := q.Query().Get("s") + + debug(2, "metadata GET request") + + service.printRequest(request) + + fullPath, err := service.fullPathToFile(share, path) + + if err != nil { + debug(2, "File not found: %s", err) + http.NotFound(writer, request) + service.debugInfo.requestServed(int64(0)) + service.accessLog(logging, request, http.StatusNotFound, 0) + return + } + + var m *Metadata + m, err = getMetadataByPath(fullPath) + if err != nil { + debug(2, "Error getting metadata: %s", err.Error()) + http.NotFound(writer, request) + service.debugInfo.requestServed(int64(0)) + service.accessLog(logging, request, http.StatusNotFound, 0) + return + } + parentDir := filepath.Dir(path) + fileName := filepath.Base(path) + index := strings.Index(fileName, ".") + artworkName := fileName[:index] + "_artwork" + ".jpg" + artworkPath := filepath.Join(parentDir,artworkName) + m.AlbumArtwork = fmt.Sprintf("/cache?s=%s&p=%s",share,artworkPath) + + b, err := json.Marshal(m) + if err != nil { + debug(2, "Internal Server Error: %s", err.Error()) + writer.WriteHeader(http.StatusInternalServerError) + service.debugInfo.requestServed(int64(0)) + service.accessLog(logging, request, http.StatusInternalServerError,0) + return + } + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + size, _ := writer.Write(b) + service.accessLog(logging, request, http.StatusOK, size) + service.debugInfo.requestServed(int64(size)) +} + func (service *MercuryFsService) accessLog(logging *Logging, request *http.Request, statusCode int, bodySize int) { var requestTime time.Time var elapsedTime time.Duration