navidrome/engine/playlists.go

118 lines
2.8 KiB
Go
Raw Normal View History

package engine
import (
2020-01-09 02:45:07 +01:00
"context"
2016-03-24 18:28:20 +01:00
"sort"
2016-03-24 17:06:39 +01:00
2017-04-01 15:47:14 +02:00
"github.com/cloudsonic/sonic-server/domain"
"github.com/cloudsonic/sonic-server/itunesbridge"
2020-01-09 02:45:07 +01:00
"github.com/cloudsonic/sonic-server/log"
)
type Playlists interface {
GetAll() (domain.Playlists, error)
2016-03-10 00:28:11 +01:00
Get(id string) (*PlaylistInfo, error)
2020-01-09 02:45:07 +01:00
Create(ctx context.Context, name string, ids []string) error
Delete(ctx context.Context, playlistId string) error
2016-03-24 18:28:20 +01:00
Update(playlistId string, name *string, idsToAdd []string, idxToRemove []int) error
}
2016-03-24 17:06:39 +01:00
func NewPlaylists(itunes itunesbridge.ItunesControl, pr domain.PlaylistRepository, mr domain.MediaFileRepository) Playlists {
return &playlists{itunes, pr, mr}
}
2016-03-10 00:28:11 +01:00
type playlists struct {
2016-03-24 17:06:39 +01:00
itunes itunesbridge.ItunesControl
2016-03-10 00:28:11 +01:00
plsRepo domain.PlaylistRepository
mfileRepo domain.MediaFileRepository
}
2016-03-22 04:11:57 +01:00
func (p *playlists) GetAll() (domain.Playlists, error) {
return p.plsRepo.GetAll(domain.QueryOptions{})
}
2016-03-10 00:28:11 +01:00
type PlaylistInfo struct {
2016-03-21 17:26:55 +01:00
Id string
Name string
Entries Entries
SongCount int
Duration int
Public bool
Owner string
2016-03-24 18:28:20 +01:00
Comment string
2016-03-10 00:28:11 +01:00
}
2020-01-09 02:45:07 +01:00
func (p *playlists) Create(ctx context.Context, name string, ids []string) error {
2016-03-24 17:06:39 +01:00
pid, err := p.itunes.CreatePlaylist(name, ids)
if err != nil {
return err
}
2020-01-09 02:45:07 +01:00
log.Info(ctx, "Created playlist", "playlist", name, "id", pid)
2016-03-24 17:06:39 +01:00
return nil
}
2020-01-09 02:45:07 +01:00
func (p *playlists) Delete(ctx context.Context, playlistId string) error {
2016-03-24 18:28:20 +01:00
err := p.itunes.DeletePlaylist(playlistId)
2016-03-24 17:17:35 +01:00
if err != nil {
return err
}
2020-01-09 02:45:07 +01:00
log.Info(ctx, "Deleted playlist", "id", playlistId)
2016-03-24 18:28:20 +01:00
return nil
}
func (p *playlists) Update(playlistId string, name *string, idsToAdd []string, idxToRemove []int) error {
pl, err := p.plsRepo.Get(playlistId)
if err != nil {
return err
}
if name != nil {
pl.Name = *name
err := p.itunes.RenamePlaylist(pl.ID, pl.Name)
2016-03-24 18:28:20 +01:00
if err != nil {
return err
}
}
if len(idsToAdd) > 0 || len(idxToRemove) > 0 {
sort.Sort(sort.Reverse(sort.IntSlice(idxToRemove)))
for _, i := range idxToRemove {
pl.Tracks, pl.Tracks[len(pl.Tracks)-1] = append(pl.Tracks[:i], pl.Tracks[i+1:]...), ""
}
pl.Tracks = append(pl.Tracks, idsToAdd...)
err := p.itunes.UpdatePlaylist(pl.ID, pl.Tracks)
2016-03-24 18:28:20 +01:00
if err != nil {
return err
}
}
2016-03-24 19:08:19 +01:00
p.plsRepo.Put(pl) // Ignores errors, as any changes will be overridden in the next scan
2016-03-24 17:17:35 +01:00
return nil
}
2016-03-22 04:11:57 +01:00
func (p *playlists) Get(id string) (*PlaylistInfo, error) {
2016-03-10 00:28:11 +01:00
pl, err := p.plsRepo.Get(id)
if err != nil {
return nil, err
}
2016-03-21 17:26:55 +01:00
pinfo := &PlaylistInfo{
Id: pl.ID,
2016-03-21 17:26:55 +01:00
Name: pl.Name,
SongCount: len(pl.Tracks),
Duration: pl.Duration,
Public: pl.Public,
Owner: pl.Owner,
2016-03-24 18:28:20 +01:00
Comment: pl.Comment,
2016-03-21 17:26:55 +01:00
}
2016-03-14 16:42:33 +01:00
pinfo.Entries = make(Entries, len(pl.Tracks))
2016-03-10 00:28:11 +01:00
// TODO Optimize: Get all tracks at once
for i, mfId := range pl.Tracks {
mf, err := p.mfileRepo.Get(mfId)
if err != nil {
return nil, err
}
2016-03-11 15:10:40 +01:00
pinfo.Entries[i] = FromMediaFile(mf)
2016-03-10 00:28:11 +01:00
}
return pinfo, nil
}