2016-03-09 05:05:54 +01:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
2016-03-18 16:33:50 +01:00
|
|
|
"bytes"
|
2016-03-09 05:31:48 +01:00
|
|
|
"image"
|
|
|
|
_ "image/gif"
|
|
|
|
"image/jpeg"
|
2016-03-18 16:33:50 +01:00
|
|
|
_ "image/png"
|
|
|
|
"io"
|
|
|
|
"os"
|
2016-03-30 16:01:37 +02:00
|
|
|
"strings"
|
2016-03-09 05:31:48 +01:00
|
|
|
|
2017-04-01 15:47:14 +02:00
|
|
|
"github.com/cloudsonic/sonic-server/domain"
|
2016-03-09 05:05:54 +01:00
|
|
|
"github.com/dhowden/tag"
|
2016-03-09 05:31:48 +01:00
|
|
|
"github.com/nfnt/resize"
|
2016-03-09 05:05:54 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type Cover interface {
|
2016-03-09 05:31:48 +01:00
|
|
|
Get(id string, size int, out io.Writer) error
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type cover struct {
|
|
|
|
mfileRepo domain.MediaFileRepository
|
2016-03-30 16:01:37 +02:00
|
|
|
albumRepo domain.AlbumRepository
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
2016-03-30 16:01:37 +02:00
|
|
|
func NewCover(mr domain.MediaFileRepository, alr domain.AlbumRepository) Cover {
|
|
|
|
return &cover{mr, alr}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *cover) getCoverPath(id string) (string, error) {
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(id, "al-"):
|
|
|
|
id = id[3:]
|
|
|
|
al, err := c.albumRepo.Get(id)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return al.CoverArtPath, nil
|
|
|
|
default:
|
|
|
|
mf, err := c.mfileRepo.Get(id)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if mf.HasCoverArt {
|
|
|
|
return mf.Path, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "", domain.ErrNotFound
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
2016-03-22 04:11:57 +01:00
|
|
|
func (c *cover) Get(id string, size int, out io.Writer) error {
|
2016-03-30 16:01:37 +02:00
|
|
|
path, err := c.getCoverPath(id)
|
2016-03-18 16:33:50 +01:00
|
|
|
if err != nil && err != domain.ErrNotFound {
|
2016-03-09 05:05:54 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-09 05:31:48 +01:00
|
|
|
var reader io.Reader
|
2016-03-09 05:05:54 +01:00
|
|
|
|
2016-03-30 16:01:37 +02:00
|
|
|
if err != domain.ErrNotFound {
|
|
|
|
reader, err = readFromTag(path)
|
2016-03-09 05:05:54 +01:00
|
|
|
} else {
|
2016-03-18 16:33:50 +01:00
|
|
|
var f *os.File
|
|
|
|
f, err = os.Open("static/default_cover.jpg")
|
2016-03-09 05:31:48 +01:00
|
|
|
if err == nil {
|
|
|
|
defer f.Close()
|
|
|
|
reader = f
|
|
|
|
}
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2016-03-23 23:15:14 +01:00
|
|
|
return domain.ErrNotFound
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 05:31:48 +01:00
|
|
|
if size > 0 {
|
|
|
|
return resizeImage(reader, size, out)
|
|
|
|
}
|
2016-03-10 15:37:35 +01:00
|
|
|
_, err = io.Copy(out, reader)
|
|
|
|
return err
|
2016-03-09 05:31:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func resizeImage(reader io.Reader, size int, out io.Writer) error {
|
|
|
|
img, _, err := image.Decode(reader)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
m := resize.Resize(uint(size), 0, img, resize.NearestNeighbor)
|
|
|
|
return jpeg.Encode(out, m, &jpeg.Options{Quality: 75})
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 05:31:48 +01:00
|
|
|
func readFromTag(path string) (io.Reader, error) {
|
2016-03-09 05:05:54 +01:00
|
|
|
f, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
m, err := tag.ReadFrom(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-03-09 05:31:48 +01:00
|
|
|
return bytes.NewReader(m.Picture().Data), nil
|
2016-03-09 05:05:54 +01:00
|
|
|
}
|