// AddFileToPlaylist function adds a file to a specific playlist. // The function also checks that the file exists in the MuLi database. func AddFileToPlaylist(file playlistmgr.PlaylistFile, playlistName string) error { path, err := GetFilePath(file.Artist, file.Album, file.Title) if err != nil { return errors.New("Playlist item not found in MuLi.") } file.Path = path db, err := bolt.Open(config.DbPath, 0600, nil) if err != nil { return err } defer db.Close() err = db.Update(func(tx *bolt.Tx) error { root := tx.Bucket([]byte("Playlists")) if root == nil { glog.Errorf("Error opening Playlists bucket: %s\n", err) return errors.New("Error opening Playlists bucket.") } playlistBucket := root.Bucket([]byte(playlistName)) if playlistBucket == nil { glog.Errorf("Error opening %s playlist bucket: %s\n", playlistName, err) return errors.New("Error opening playlist bucket.") } encoded, err := json.Marshal(file) if err != nil { glog.Errorf("Cannot encode PlaylistFile.") return err } playlistBucket.Put([]byte(file.Title), encoded) // Update the original file playlists to have a link to the // current playlist. root = tx.Bucket([]byte("Artists")) if root == nil { glog.Errorf("Error opening Artists bucket: %s\n", err) return errors.New("Error opening Artists bucket.") } artistBucket := root.Bucket([]byte(file.Artist)) if artistBucket == nil { glog.Errorf("Error opening %s artist bucket: %s\n", file.Artist, err) return errors.New("Error opening artist bucket.") } albumBucket := artistBucket.Bucket([]byte(file.Album)) if albumBucket == nil { glog.Errorf("Error opening %s album on %s artist: %s\n", file.Album, file.Artist, err) return errors.New("Error opening album bucket.") } songJson := albumBucket.Get([]byte(file.Title)) if songJson == nil { glog.Errorf("Error opening %s on %s album on %s artist: %s\n", file.Title, file.Album, file.Artist, err) return errors.New("Error opening song json.") } var song SongStore err = json.Unmarshal(songJson, &song) if err != nil { return err } if song.Playlists != nil { for _, list := range song.Playlists { if list == playlistName { return nil } } } song.Playlists = append(song.Playlists, playlistName) encoded, err = json.Marshal(song) if err != nil { return err } return albumBucket.Put([]byte(file.Title), encoded) }) return err }
// DelayedHandlePlaylistSong handles a dropped file // inside a playlist and is called by the background // dispatcher after some time has passed. func DelayedHandlePlaylistSong(f File) error { rootPoint := f.mPoint if rootPoint[len(rootPoint)-1] != '/' { rootPoint = rootPoint + "/" } path := rootPoint + "playlists/" + f.album + "/" + f.name extension := filepath.Ext(f.name) if extension != ".mp3" { os.Remove(path) return errors.New("File is not an mp3.") } src, err := os.Stat(path) if err != nil || src.IsDir() { return errors.New("File not found.") } err, tags := musicmgr.GetMp3Tags(path) if err != nil { os.Remove(path) return err } artist := store.GetCompatibleString(tags.Artist) album := store.GetCompatibleString(tags.Album) title := tags.Title if strings.HasSuffix(title, ".mp3") { title = title[:len(title)-len(".mp3")] } title = store.GetCompatibleString(title) + ".mp3" newPath, err := store.GetFilePath(artist, album, title) if err == nil { var playlistFile playlistmgr.PlaylistFile playlistFile.Title = title playlistFile.Artist = artist playlistFile.Album = album playlistFile.Path = newPath err = store.AddFileToPlaylist(playlistFile, f.album) } else { err = store.HandleDrop(path, rootPoint) if err == nil { newPath, err = store.GetFilePath(artist, album, title) if err == nil { var playlistFile playlistmgr.PlaylistFile playlistFile.Title = title playlistFile.Artist = artist playlistFile.Album = album playlistFile.Path = newPath err = store.AddFileToPlaylist(playlistFile, f.album) } } } os.Remove(path) if err == nil { err = store.RegeneratePlaylistFile(f.album, rootPoint) } return err }