func Read(rf codec.Reader) (codec.Songs, error) { r, _, err := rf() if err != nil { return nil, err } // In order to not open the rar file up once per included file, keep around a // pointer to the reader during the inital listing phase and use that if we're // opening it. I would appreciate a better way to do this. var rd *rardecode.Reader var rfh *rardecode.FileHeader defer func() { rd = nil }() readRAR := func(name string, rf codec.Reader) codec.Reader { return func() (rc io.ReadCloser, sz int64, err error) { if rd != nil && rfh.Name == name { return ioutil.NopCloser(rd), rfh.UnPackedSize, nil } r, _, err := rf() if err != nil { return nil, 0, err } f := func(d *rardecode.Reader, fh *rardecode.FileHeader) (stop bool) { if fh.Name != name { return false } rc = &rarReader{r, d} sz = fh.UnPackedSize return true } err = read(r, f) if err == nil && rc == nil { err = fmt.Errorf("rar: %v unfound", name) } return } } defer r.Close() songs := make(codec.Songs) f := func(d *rardecode.Reader, fh *rardecode.FileHeader) (stop bool) { rd = d rfh = fh ss, _, _ := codec.ByExtension(fh.Name, readRAR(fh.Name, rf)) for v, s := range ss { songs[codec.NewID(fh.Name, string(v))] = s } return false } if err := read(r, f); err != nil { return nil, err } return songs, nil }
func (d *Dropbox) Refresh() (protocol.SongList, error) { service, err := d.getService() if err != nil { return nil, err } files := make(map[string]*dropbox.ListContent) songs := make(protocol.SongList) var ss codec.Songs dirs := []string{""} for { if len(dirs) == 0 { break } dir := dirs[0] dirs = dirs[1:] list, err := service.List().Path(dir).Do() if err != nil { return nil, err } for _, f := range list.Contents { if f.IsDir { dirs = append(dirs, f.Path) continue } ss, _, err = codec.ByExtension(f.Path, d.reader(f.Path, f.Bytes)) if err != nil || len(ss) == 0 { continue } files[f.Path] = f for i, v := range ss { info, _ := v.Info() if info.Title == "" { title := path.Base(f.Path) if len(ss) != 1 { title += fmt.Sprintf(":%v", i) } info.Title = title } if info.Album == "" { info.Album = path.Base(dir) } songs[codec.NewID(f.Path, string(i))] = &info } } } d.Songs = songs d.Files = files return songs, err }
func (d *Drive) Refresh() (protocol.SongList, error) { service, err := d.getService() if err != nil { return nil, err } files := make(map[string]*drive.File) songs := make(protocol.SongList) var nextPage string var ss codec.Songs for { fl, err := service.Files. List(). PageToken(nextPage). Fields("nextPageToken", "files(fileExtension,id,name,size)"). PageSize(1000). Do() if err != nil { return nil, err } nextPage = fl.NextPageToken for _, f := range fl.Files { ss, _, err = codec.ByExtension(f.FileExtension, d.reader(f.Id)) if err != nil || len(ss) == 0 { continue } files[f.Id] = f for i, v := range ss { info, _ := v.Info() if info.Title == "" { title := f.Name if len(ss) != 1 { title += fmt.Sprintf(":%v", i) } info.Title = title } songs[codec.NewID(f.Id, string(i))] = &info } } if nextPage == "" { break } } d.Songs = songs d.Files = files return songs, err }
func (f *File) Refresh() (protocol.SongList, error) { songs := make(protocol.SongList) err := filepath.Walk(f.Path, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } f, err := os.Open(path) if err != nil { return nil } defer f.Close() ss, _, err := codec.ByExtension(path, fileReader(path)) if err != nil || len(ss) == 0 { return nil } for i, s := range ss { info, _ := s.Info() if info.Title == "" { title := filepath.Base(path) if len(ss) != 1 { title += fmt.Sprintf(":%v", i) } info.Title = title } if info.Album == "" { info.Album = filepath.Base(filepath.Dir(path)) } songs[codec.NewID(path, string(i))] = &info } return nil }) f.Songs = songs return songs, err }