diff --git a/api/base_api_controller.go b/api/base_api_controller.go index 4f462f1d4..bdca8df4e 100644 --- a/api/base_api_controller.go +++ b/api/base_api_controller.go @@ -7,6 +7,7 @@ import ( "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" + "github.com/deluan/gosonic/engine" "github.com/deluan/gosonic/utils" ) @@ -70,3 +71,26 @@ func (c *BaseAPIController) SendResponse(response responses.Subsonic) { c.ServeXML() } } + +func (c *BaseAPIController) ToChild(entry engine.Entry) responses.Child { + n := responses.Child{} + n.Id = entry.Id + n.Title = entry.Title + n.IsDir = entry.IsDir + n.Parent = entry.Parent + n.Album = entry.Album + n.Year = entry.Year + n.Artist = entry.Artist + n.Genre = entry.Genre + n.CoverArt = entry.CoverArt + n.Track = entry.Track + n.Duration = entry.Duration + n.Size = entry.Size + n.Suffix = entry.Suffix + n.BitRate = entry.BitRate + n.ContentType = entry.ContentType + if !entry.Starred.IsZero() { + n.Starred = &entry.Starred + } + return n +} diff --git a/api/browsing.go b/api/browsing.go index d05f4dad0..e9057e836 100644 --- a/api/browsing.go +++ b/api/browsing.go @@ -84,26 +84,9 @@ func (c *BrowsingController) GetDirectory() { func (c *BrowsingController) buildDirectory(d *engine.DirectoryInfo) *responses.Directory { dir := &responses.Directory{Id: d.Id, Name: d.Name} - dir.Child = make([]responses.Child, len(d.Children)) - for i, child := range d.Children { - dir.Child[i].Id = child.Id - dir.Child[i].Title = child.Title - dir.Child[i].IsDir = child.IsDir - dir.Child[i].Parent = child.Parent - dir.Child[i].Album = child.Album - dir.Child[i].Year = child.Year - dir.Child[i].Artist = child.Artist - dir.Child[i].Genre = child.Genre - dir.Child[i].CoverArt = child.CoverArt - dir.Child[i].Track = child.Track - dir.Child[i].Duration = child.Duration - dir.Child[i].Size = child.Size - dir.Child[i].Suffix = child.Suffix - dir.Child[i].BitRate = child.BitRate - dir.Child[i].ContentType = child.ContentType - if !child.Starred.IsZero() { - dir.Child[i].Starred = &child.Starred - } + dir.Child = make([]responses.Child, len(d.Entries)) + for i, entry := range d.Entries { + dir.Child[i] = c.ToChild(entry) } return dir } diff --git a/api/search.go b/api/search.go index 9efbf975d..384b6cb1c 100644 --- a/api/search.go +++ b/api/search.go @@ -29,15 +29,30 @@ func (c *SearchingController) Search2() { as, err := c.search.SearchArtist(query, artistOffset, artistCount) if err != nil { beego.Error("Error searching for Artists:", err) - c.SendError(responses.ERROR_GENERIC, "Internal Error") } + //als, err := c.search.SearchAlbum(query, albumOffset, albumCount) + //if err != nil { + // beego.Error("Error searching for Albums:", err) + //} + //mfs, err := c.search.SearchSong(query, songOffset, songCount) + //if err != nil { + // beego.Error("Error searching for MediaFiles:", err) + //} response := c.NewEmpty() searchResult2 := &responses.SearchResult2{} searchResult2.Artist = make([]responses.Artist, len(*as)) for i, a := range *as { - searchResult2.Artist[i] = responses.Artist{Id: a.Id, Name: a.Name} + searchResult2.Artist[i] = responses.Artist{Id: a.Id, Name: a.Title} } + //searchResult2.Album = make([]responses.Child, len(*as)) + //for i, a := range *as { + // searchResult2.Album[i] = responses.Child{Id: a.Id, Name: a.Name} + //} + //searchResult2.Artist = make([]responses.Artist, len(*as)) + //for i, a := range *as { + // searchResult2.Artist[i] = responses.Artist{Id: a.Id, Name: a.Name} + //} response.SearchResult2 = searchResult2 c.SendResponse(response) } diff --git a/engine/browser.go b/engine/browser.go index e891199b9..3aef62025 100644 --- a/engine/browser.go +++ b/engine/browser.go @@ -54,9 +54,9 @@ func (b browser) Indexes(ifModifiedSince time.Time) (*domain.ArtistIndexes, time } type DirectoryInfo struct { - Id string - Name string - Children []Child + Id string + Name string + Entries []Entry } func (c browser) Directory(id string) (*DirectoryInfo, error) { @@ -87,21 +87,9 @@ func (c browser) Directory(id string) (*DirectoryInfo, error) { func (c browser) buildArtistDir(a *domain.Artist, albums *domain.Albums) *DirectoryInfo { dir := &DirectoryInfo{Id: a.Id, Name: a.Name} - dir.Children = make([]Child, len(*albums)) + dir.Entries = make([]Entry, len(*albums)) for i, al := range *albums { - dir.Children[i].Id = al.Id - dir.Children[i].Title = al.Name - dir.Children[i].IsDir = true - dir.Children[i].Parent = al.ArtistId - dir.Children[i].Album = al.Name - dir.Children[i].Year = al.Year - dir.Children[i].Artist = al.AlbumArtist - dir.Children[i].Genre = al.Genre - dir.Children[i].CoverArt = al.CoverArtId - if al.Starred { - dir.Children[i].Starred = al.UpdatedAt - } - + dir.Entries[i] = FromAlbum(&al) } return dir } @@ -109,28 +97,9 @@ func (c browser) buildArtistDir(a *domain.Artist, albums *domain.Albums) *Direct func (c browser) buildAlbumDir(al *domain.Album, tracks *domain.MediaFiles) *DirectoryInfo { dir := &DirectoryInfo{Id: al.Id, Name: al.Name} - dir.Children = make([]Child, len(*tracks)) + dir.Entries = make([]Entry, len(*tracks)) for i, mf := range *tracks { - dir.Children[i].Id = mf.Id - dir.Children[i].Title = mf.Title - dir.Children[i].IsDir = false - dir.Children[i].Parent = mf.AlbumId - dir.Children[i].Album = mf.Album - dir.Children[i].Year = mf.Year - dir.Children[i].Artist = mf.Artist - dir.Children[i].Genre = mf.Genre - dir.Children[i].Track = mf.TrackNumber - dir.Children[i].Duration = mf.Duration - dir.Children[i].Size = mf.Size - dir.Children[i].Suffix = mf.Suffix - dir.Children[i].BitRate = mf.BitRate - if mf.Starred { - dir.Children[i].Starred = mf.UpdatedAt - } - if mf.HasCoverArt { - dir.Children[i].CoverArt = mf.Id - } - dir.Children[i].ContentType = mf.ContentType() + dir.Entries[i] = FromMediaFile(&mf) } return dir } diff --git a/engine/common.go b/engine/common.go index 2b9d2d2b3..1821c8a29 100644 --- a/engine/common.go +++ b/engine/common.go @@ -3,9 +3,11 @@ package engine import ( "errors" "time" + + "github.com/deluan/gosonic/domain" ) -type Child struct { +type Entry struct { Id string Title string IsDir bool @@ -27,3 +29,45 @@ type Child struct { var ( ErrDataNotFound = errors.New("Data Not Found") ) + +func FromAlbum(al *domain.Album) Entry { + c := Entry{} + c.Id = al.Id + c.Title = al.Name + c.IsDir = true + c.Parent = al.ArtistId + c.Album = al.Name + c.Year = al.Year + c.Artist = al.AlbumArtist + c.Genre = al.Genre + c.CoverArt = al.CoverArtId + if al.Starred { + c.Starred = al.UpdatedAt + } + return c +} + +func FromMediaFile(mf *domain.MediaFile) Entry { + c := Entry{} + c.Id = mf.Id + c.Title = mf.Title + c.IsDir = false + c.Parent = mf.AlbumId + c.Album = mf.Album + c.Year = mf.Year + c.Artist = mf.Artist + c.Genre = mf.Genre + c.Track = mf.TrackNumber + c.Duration = mf.Duration + c.Size = mf.Size + c.Suffix = mf.Suffix + c.BitRate = mf.BitRate + if mf.Starred { + c.Starred = mf.UpdatedAt + } + if mf.HasCoverArt { + c.CoverArt = mf.Id + } + c.ContentType = mf.ContentType() + return c +} diff --git a/engine/playlists.go b/engine/playlists.go index 834e8ad67..2807eacc6 100644 --- a/engine/playlists.go +++ b/engine/playlists.go @@ -25,7 +25,7 @@ func (p playlists) GetAll() (*domain.Playlists, error) { type PlaylistInfo struct { Id string Name string - Entries []Child + Entries []Entry } func (p playlists) Get(id string) (*PlaylistInfo, error) { @@ -39,7 +39,7 @@ func (p playlists) Get(id string) (*PlaylistInfo, error) { } pinfo := &PlaylistInfo{Id: pl.Id, Name: pl.Name} - pinfo.Entries = make([]Child, len(pl.Tracks)) + pinfo.Entries = make([]Entry, len(pl.Tracks)) // TODO Optimize: Get all tracks at once for i, mfId := range pl.Tracks { @@ -47,26 +47,8 @@ func (p playlists) Get(id string) (*PlaylistInfo, error) { if err != nil { return nil, err } - pinfo.Entries[i].Id = mf.Id - pinfo.Entries[i].Title = mf.Title - pinfo.Entries[i].IsDir = false - pinfo.Entries[i].Parent = mf.AlbumId - pinfo.Entries[i].Album = mf.Album - pinfo.Entries[i].Year = mf.Year - pinfo.Entries[i].Artist = mf.Artist - pinfo.Entries[i].Genre = mf.Genre - //pinfo.Entries[i].Track = mf.TrackNumber - pinfo.Entries[i].Duration = mf.Duration - pinfo.Entries[i].Size = mf.Size - pinfo.Entries[i].Suffix = mf.Suffix - pinfo.Entries[i].BitRate = mf.BitRate - if mf.Starred { - pinfo.Entries[i].Starred = mf.UpdatedAt - } - if mf.HasCoverArt { - pinfo.Entries[i].CoverArt = mf.Id - } - pinfo.Entries[i].ContentType = mf.ContentType() + pinfo.Entries[i] = FromMediaFile(mf) + pinfo.Entries[i].Track = 0 } return pinfo, nil diff --git a/engine/search.go b/engine/search.go index b24d4a039..e89c298fc 100644 --- a/engine/search.go +++ b/engine/search.go @@ -7,15 +7,17 @@ import ( "github.com/deluan/gosonic/domain" ) +type Results []Entry + type Search interface { ClearAll() error IndexArtist(ar *domain.Artist) error IndexAlbum(al *domain.Album) error IndexMediaFile(mf *domain.MediaFile) error - SearchArtist(q string, offset int, size int) (*domain.Artists, error) - //SearchAlbum(q string, offset int, size int) (*domain.Albums, error) - //SearchSong(q string, offset int, size int) (*domain.MediaFiles, error) + SearchArtist(q string, offset int, size int) (*Results, error) + SearchAlbum(q string, offset int, size int) (*Results, error) + SearchSong(q string, offset int, size int) (*Results, error) } type search struct { @@ -59,29 +61,53 @@ func (s search) IndexMediaFile(mf *domain.MediaFile) error { return s.idxSong.Index(mf.Id, strings.ToLower(mf.Title)) } -func (s search) SearchArtist(q string, offset int, size int) (*domain.Artists, error) { +func (s search) SearchArtist(q string, offset int, size int) (*Results, error) { q = strings.TrimSuffix(q, "*") - res, err := s.sArtist.Search(q) + resp, err := s.sArtist.Search(q) if err != nil { return nil, nil } - as := make(domain.Artists, 0, len(res)) - for _, id := range res { + res := make(Results, 0, len(resp)) + for i, id := range resp { a, err := s.artistRepo.Get(id) if err != nil { return nil, err } - as = append(as, *a) + res[i] = Entry{Id: a.Id, Title: a.Name, IsDir: true} } - return &as, nil + return &res, nil } -//func (s search) SearchAlbum(q string, offset int, size int) (*domain.Albums, error) { -// q := strings.TrimSuffix(q, "*") -// return nil -//} -// -//func (s search) SearchSong(q string, offset int, size int) (*domain.MediaFiles, error) { -// q := strings.TrimSuffix(q, "*") -// return nil -//} +func (s search) SearchAlbum(q string, offset int, size int) (*Results, error) { + q = strings.TrimSuffix(q, "*") + resp, err := s.sAlbum.Search(q) + if err != nil { + return nil, nil + } + res := make(Results, 0, len(resp)) + for i, id := range resp { + al, err := s.albumRepo.Get(id) + if err != nil { + return nil, err + } + res[i] = FromAlbum(al) + } + return &res, nil +} + +func (s search) SearchSong(q string, offset int, size int) (*Results, error) { + q = strings.TrimSuffix(q, "*") + resp, err := s.sSong.Search(q) + if err != nil { + return nil, nil + } + res := make(Results, 0, len(resp)) + for i, id := range resp { + mf, err := s.mfileRepo.Get(id) + if err != nil { + return nil, err + } + res[i] = FromMediaFile(mf) + } + return &res, nil +}