// 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
}
Exemple #2
0
// 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
}