diff --git a/api/playlists.go b/api/playlists.go
new file mode 100644
index 00000000..9bd4d64d
--- /dev/null
+++ b/api/playlists.go
@@ -0,0 +1,34 @@
+package api
+
+import (
+ "github.com/astaxie/beego"
+ "github.com/deluan/gosonic/api/responses"
+ "github.com/deluan/gosonic/engine"
+ "github.com/deluan/gosonic/utils"
+ "github.com/karlkfi/inject"
+)
+
+type PlaylistsController struct {
+ BaseAPIController
+ pls engine.Playlists
+}
+
+func (c *PlaylistsController) Prepare() {
+ inject.ExtractAssignable(utils.Graph, &c.pls)
+}
+
+func (c *PlaylistsController) GetAll() {
+ allPls, err := c.pls.GetAll()
+ if err != nil {
+ beego.Error(err)
+ c.SendError(responses.ERROR_GENERIC, "Internal error")
+ }
+ playlists := make([]responses.Playlist, len(*allPls))
+ for i, f := range *allPls {
+ playlists[i].Id = f.Id
+ playlists[i].Name = f.Name
+ }
+ response := c.NewEmpty()
+ response.Playlists = &responses.Playlists{Playlist: playlists}
+ c.SendResponse(response)
+}
diff --git a/api/responses/responses.go b/api/responses/responses.go
index 1b635560..6f53b1fe 100644
--- a/api/responses/responses.go
+++ b/api/responses/responses.go
@@ -14,8 +14,9 @@ type Subsonic struct {
MusicFolders *MusicFolders `xml:"musicFolders,omitempty" json:"musicFolders,omitempty"`
Indexes *Indexes `xml:"indexes,omitempty" json:"indexes,omitempty"`
Directory *Directory `xml:"directory,omitempty" json:"directory,omitempty"`
- User *User `xml:"user,omitempty" json:"user,omitempty"`
+ User *User `xml:"user,omitempty" json:"user,omitempty"`
AlbumList *AlbumList `xml:"albumList,omitempty" json:"albumList,omitempty"`
+ Playlists *Playlists `xml:"playlists,omitempty" json:"playlists,omitempty"`
}
type JsonWrapper struct {
@@ -87,6 +88,31 @@ type AlbumList struct {
Album []Child `xml:"album" json:"album,omitempty"`
}
+type Playlist struct {
+ Id string `xml:"id,attr" json:"id"`
+ Name string `xml:"name,attr" json:"name"`
+ /*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ */
+}
+
+type Playlists struct {
+ Playlist []Playlist `xml:"playlist" json:"playlist,omitempty"`
+}
+
type User struct {
Username string `xml:"username,attr" json:"username"`
Email string `xml:"email,attr,omitempty" json:"email,omitempty"`
diff --git a/api/responses/responses_test.go b/api/responses/responses_test.go
index af7a6867..da622812 100644
--- a/api/responses/responses_test.go
+++ b/api/responses/responses_test.go
@@ -1,11 +1,12 @@
package responses_test
import (
+ "testing"
+ "time"
+
. "github.com/deluan/gosonic/api/responses"
. "github.com/deluan/gosonic/tests"
. "github.com/smartystreets/goconvey/convey"
- "testing"
- "time"
)
func TestSubsonicResponses(t *testing.T) {
@@ -172,6 +173,31 @@ func TestSubsonicResponses(t *testing.T) {
})
})
})
+ Convey("Playlists", func() {
+ response.Playlists = &Playlists{}
+
+ Convey("Without data", func() {
+ Convey("XML", func() {
+ So(response, ShouldMatchXML, ``)
+ })
+ Convey("JSON", func() {
+ So(response, ShouldMatchJSON, `{"playlists":{},"status":"ok","version":"1.0.0"}`)
+ })
+ })
+ Convey("With data", func() {
+ pls := make([]Playlist, 2)
+ pls[0] = Playlist{Id: "111", Name: "aaa"}
+ pls[1] = Playlist{Id: "222", Name: "bbb"}
+ response.Playlists.Playlist = pls
+
+ Convey("XML", func() {
+ So(response, ShouldMatchXML, ``)
+ })
+ Convey("JSON", func() {
+ So(response, ShouldMatchJSON, `{"playlists":{"playlist":[{"id":"111","name":"aaa"},{"id":"222","name":"bbb"}]},"status":"ok","version":"1.0.0"}`)
+ })
+ })
+ })
Reset(func() {
response = &Subsonic{Status: "ok", Version: "1.0.0"}
diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go
index 131e46fc..2ef02d16 100644
--- a/conf/inject_definitions.go
+++ b/conf/inject_definitions.go
@@ -14,10 +14,12 @@ func init() {
utils.DefineSingleton(new(domain.ArtistRepository), persistence.NewArtistRepository)
utils.DefineSingleton(new(domain.AlbumRepository), persistence.NewAlbumRepository)
utils.DefineSingleton(new(domain.MediaFileRepository), persistence.NewMediaFileRepository)
+ utils.DefineSingleton(new(domain.PlaylistRepository), persistence.NewPlaylistRepository)
// Engine (Use cases)
utils.DefineSingleton(new(engine.PropertyRepository), persistence.NewPropertyRepository)
utils.DefineSingleton(new(engine.Browser), engine.NewBrowser)
utils.DefineSingleton(new(engine.ListGenerator), engine.NewListGenerator)
utils.DefineSingleton(new(engine.Cover), engine.NewCover)
+ utils.DefineSingleton(new(engine.Playlists), engine.NewPlaylists)
}
diff --git a/conf/router.go b/conf/router.go
index 48b436ab..ad38c838 100644
--- a/conf/router.go
+++ b/conf/router.go
@@ -26,6 +26,7 @@ func mapEndpoints() {
beego.NSRouter("/download.view", &api.StreamController{}, "*:Download"),
beego.NSRouter("/getUser.view", &api.UsersController{}, "*:GetUser"),
beego.NSRouter("/getAlbumList.view", &api.GetAlbumListController{}, "*:Get"),
+ beego.NSRouter("/getPlaylists.view", &api.PlaylistsController{}, "*:GetAll"),
)
beego.AddNamespace(ns)
diff --git a/domain/playlist.go b/domain/playlist.go
new file mode 100644
index 00000000..7dc3c021
--- /dev/null
+++ b/domain/playlist.go
@@ -0,0 +1,17 @@
+package domain
+
+type Playlist struct {
+ Id string
+ Name string
+ Tracks []string
+}
+
+type PlaylistRepository interface {
+ BaseRepository
+ Put(m *Playlist) error
+ Get(id string) (*Playlist, error)
+ GetAll(options QueryOptions) (*Playlists, error)
+ PurgeInactive(active *Playlists) error
+}
+
+type Playlists []Playlist
diff --git a/engine/playlists.go b/engine/playlists.go
new file mode 100644
index 00000000..ee23536f
--- /dev/null
+++ b/engine/playlists.go
@@ -0,0 +1,21 @@
+package engine
+
+import (
+ "github.com/deluan/gosonic/domain"
+)
+
+type Playlists interface {
+ GetAll() (*domain.Playlists, error)
+}
+
+type playlists struct {
+ plsRepo domain.PlaylistRepository
+}
+
+func NewPlaylists(pr domain.PlaylistRepository) Playlists {
+ return playlists{pr}
+}
+
+func (p playlists) GetAll() (*domain.Playlists, error) {
+ return p.plsRepo.GetAll(domain.QueryOptions{})
+}
diff --git a/persistence/playlist_repository.go b/persistence/playlist_repository.go
new file mode 100644
index 00000000..0617c858
--- /dev/null
+++ b/persistence/playlist_repository.go
@@ -0,0 +1,55 @@
+package persistence
+
+import (
+ "errors"
+
+ "github.com/deluan/gosonic/domain"
+)
+
+type playlistRepository struct {
+ ledisRepository
+}
+
+func NewPlaylistRepository() domain.PlaylistRepository {
+ r := &playlistRepository{}
+ r.init("playlist", &domain.Playlist{})
+ return r
+}
+
+func (r *playlistRepository) Put(m *domain.Playlist) error {
+ if m.Id == "" {
+ return errors.New("Playlist Id is not set")
+ }
+ return r.saveOrUpdate(m.Id, m)
+}
+
+func (r *playlistRepository) Get(id string) (*domain.Playlist, error) {
+ var rec interface{}
+ rec, err := r.readEntity(id)
+ return rec.(*domain.Playlist), err
+}
+
+func (r *playlistRepository) GetAll(options domain.QueryOptions) (*domain.Playlists, error) {
+ var as = make(domain.Playlists, 0)
+ err := r.loadAll(&as, options)
+ return &as, err
+}
+
+func (r *playlistRepository) PurgeInactive(active *domain.Playlists) error {
+ currentIds, err := r.getAllIds()
+ if err != nil {
+ return err
+ }
+ for _, a := range *active {
+ currentIds[a.Id] = false
+ }
+ inactiveIds := make(map[string]bool)
+ for id, inactive := range currentIds {
+ if inactive {
+ inactiveIds[id] = true
+ }
+ }
+ return r.DeleteAll(inactiveIds)
+}
+
+var _ domain.PlaylistRepository = (*playlistRepository)(nil)