func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) error { if fh.r == nil { if fh.f.name == ".description" { glog.Infof("Entered Release: .description file\n") return nil } if fh.f.name[0] == '.' { return fuse.EPERM } } if fh.r == nil { glog.Info("Release: There is no file handler.\n") return fuse.EIO } glog.Infof("Releasing the file: %s\n", fh.r.Name()) if fh.f != nil && fh.f.artist == "drop" { glog.Infof("Entered Release dropping the song: %s\n", fh.f.name) ret_val := fh.r.Close() PushFileItem(*fh.f, DelayedHandleDrop) return ret_val } if fh.f != nil && fh.f.artist == "playlists" { glog.Infof("Entered Release with playlist song: %s\n", fh.f.name) ret_val := fh.r.Close() PushFileItem(*fh.f, DelayedHandlePlaylistSong) return ret_val } // This is not an music file or this is a strange situation. if fh.f == nil || len(fh.f.artist) < 1 || len(fh.f.album) < 1 { glog.Info("Entered Release: Artist or Album not set.\n") return fh.r.Close() } glog.Infof("Entered Release: Artist: %s, Album: %s, Song: %s\n", fh.f.artist, fh.f.album, fh.f.name) ret_val := fh.r.Close() extension := filepath.Ext(fh.f.name) songPath, err := store.GetFilePath(fh.f.artist, fh.f.album, fh.f.name) if err != nil { return err } if extension == ".mp3" { //TODO: Use the correct artist and album musicmgr.SetMp3Tags(fh.f.artist, fh.f.album, fh.f.song, songPath) } return ret_val }
func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) { glog.Infof("Entered Open with file name: %s.\n", f.name) if f.name == ".description" { return &FileHandle{r: nil, f: f}, nil } if f.name[0] == '.' { return nil, fuse.EPERM } if runtime.GOOS == "darwin" { resp.Flags |= fuse.OpenDirectIO } if req.Flags.IsReadOnly() { glog.Info("Open: File requested is read only.\n") } if req.Flags.IsReadWrite() { glog.Info("Open: File requested is read write.\n") } if req.Flags.IsWriteOnly() { glog.Info("Open: File requested is write only.\n") } var err error var songPath string if f.artist == "drop" { songPath, err = store.GetDropFilePath(f.name, f.mPoint) PushFileItem(*f, DelayedVoid) } else if f.artist == "playlists" { songPath, err = store.GetPlaylistFilePath(f.album, f.name, f.mPoint) PushFileItem(*f, DelayedVoid) } else { songPath, err = store.GetFilePath(f.artist, f.album, f.name) } if err != nil { glog.Error(err) return nil, err } r, err := os.OpenFile(songPath, int(req.Flags), 0666) if err != nil { return nil, err } return &FileHandle{r: r, f: f}, nil }
func (f *File) Attr(ctx context.Context, a *fuse.Attr) error { glog.Infof("Entering file Attr with name: %s, Artist: %s and Album: %s.\n", f.name, f.artist, f.album) if f.name[0] == '.' { if f.name == ".description" { descriptionJson, err := store.GetDescription(f.artist, f.album, f.name) if err != nil { return err } a.Size = uint64(len(descriptionJson)) a.Mode = 0444 if config_params.uid != 0 { a.Uid = uint32(config_params.uid) } if config_params.gid != 0 { a.Gid = uint32(config_params.gid) } } else { return fuse.EPERM } } else { var songPath string var err error if f.artist == "drop" { songPath, err = store.GetDropFilePath(f.name, f.mPoint) PushFileItem(*f, nil) } else if f.artist == "playlists" { songPath, err = store.GetPlaylistFilePath(f.album, f.name, f.mPoint) PushFileItem(*f, nil) } else { songPath, err = store.GetFilePath(f.artist, f.album, f.name) } if err != nil { glog.Infof("Error getting song path: %s\n", err) return err } r, err := os.Open(songPath) if err != nil { glog.Infof("Error opening file: %s\n", err) return err } defer r.Close() fi, err := r.Stat() if err != nil { glog.Infof("Error getting file status: %s\n", err) return err } a.Size = uint64(fi.Size()) a.Mode = 0777 if config_params.uid != 0 { a.Uid = uint32(config_params.uid) } if config_params.gid != 0 { a.Gid = uint32(config_params.gid) } } return nil }
// 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 }
func (d *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) { glog.Infof("Entering Lookup with artist: %s, album: %s and name: %s.\n", d.artist, d.album, name) if name == ".description" { return &File{artist: d.artist, album: d.album, song: name, name: name, mPoint: d.mPoint}, nil } if name[0] == '.' { return nil, fuse.EIO } if len(d.artist) < 1 { if name == "drop" { return &Dir{fs: d.fs, artist: "drop", album: "", mPoint: d.mPoint}, nil } if name == "playlists" { return &Dir{fs: d.fs, artist: "playlists", album: "", mPoint: d.mPoint}, nil } _, err := store.GetArtistPath(name) if err != nil { glog.Info(err) return nil, err } return &Dir{fs: d.fs, artist: name, album: "", mPoint: d.mPoint}, nil } if len(d.album) < 1 && d.artist != "drop" && d.artist != "playlists" { _, err := store.GetAlbumPath(d.artist, name) if err != nil { glog.Info(err) return nil, err } return &Dir{fs: d.fs, artist: d.artist, album: name, mPoint: d.mPoint}, nil } var err error if d.artist == "drop" { _, err = store.GetDropFilePath(name, d.mPoint) if err != nil { glog.Info(err) return nil, fuse.ENOENT } } else if d.artist == "playlists" { if len(d.album) < 1 { _, err = store.GetPlaylistPath(name) if err != nil { glog.Info(err) return nil, fuse.ENOENT } return &Dir{fs: d.fs, artist: d.artist, album: name, mPoint: d.mPoint}, nil } else { _, err = store.GetPlaylistFilePath(d.album, name, d.mPoint) if err != nil { glog.Info(err) return nil, fuse.ENOENT } } } else { _, err = store.GetFilePath(d.artist, d.album, name) if err != nil { glog.Info(err) return nil, err } } extension := filepath.Ext(name) songName := name[:len(name)-len(extension)] return &File{artist: d.artist, album: d.album, song: songName, name: name, mPoint: d.mPoint}, nil }
func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { //TODO: Correct this function to work with drop folder. name := req.Name glog.Infof("Entered Remove function with Artist: %s, Album: %s and Name: %s.\n", d.artist, d.album, name) if name == ".description" { return nil } if name[0] == '.' { return fuse.EIO } if req.Dir { if len(name) < 1 { return fuse.EIO } if len(d.artist) < 1 { if name == "drop" { return fuse.EIO } if name == "playlists" { return fuse.EIO } err := store.DeleteArtist(name, d.mPoint) if err != nil { return fuse.EIO } return nil } if d.artist == "playlists" { store.DeletePlaylist(name, d.mPoint) return nil } err := store.DeleteAlbum(d.artist, name, d.mPoint) if err != nil { return fuse.EIO } return nil } else { if len(d.artist) < 1 || len(d.album) < 1 { return fuse.EIO } fullPath, err := store.GetFilePath(d.artist, d.album, name) if err != nil { return fuse.EIO } if d.artist == "playlists" { err := store.DeletePlaylistSong(d.album, name, false) if err != nil { return fuse.EIO } } err = store.DeleteSong(d.artist, d.album, name, d.mPoint) if err != nil { return fuse.EIO } //TODO: Check if there are no more files in the folder // and delete the folder. err = os.Remove(fullPath) if err != nil { return err } return nil } }