feat(server): add M3U file to downloaded playlist
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
+28
-3
@@ -98,7 +98,7 @@ func (a *archiver) ZipShare(ctx context.Context, id string, out io.Writer) error
|
|||||||
return model.ErrNotAuthorized
|
return model.ErrNotAuthorized
|
||||||
}
|
}
|
||||||
log.Debug(ctx, "Zipping share", "name", s.ID, "format", s.Format, "bitrate", s.MaxBitRate, "numTracks", len(s.Tracks))
|
log.Debug(ctx, "Zipping share", "name", s.ID, "format", s.Format, "bitrate", s.MaxBitRate, "numTracks", len(s.Tracks))
|
||||||
return a.zipMediaFiles(ctx, id, s.Format, s.MaxBitRate, out, s.Tracks)
|
return a.zipMediaFiles(ctx, id, s.ID, s.Format, s.MaxBitRate, out, s.Tracks, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *archiver) ZipPlaylist(ctx context.Context, id string, format string, bitrate int, out io.Writer) error {
|
func (a *archiver) ZipPlaylist(ctx context.Context, id string, format string, bitrate int, out io.Writer) error {
|
||||||
@@ -109,15 +109,40 @@ func (a *archiver) ZipPlaylist(ctx context.Context, id string, format string, bi
|
|||||||
}
|
}
|
||||||
mfs := pls.MediaFiles()
|
mfs := pls.MediaFiles()
|
||||||
log.Debug(ctx, "Zipping playlist", "name", pls.Name, "format", format, "bitrate", bitrate, "numTracks", len(mfs))
|
log.Debug(ctx, "Zipping playlist", "name", pls.Name, "format", format, "bitrate", bitrate, "numTracks", len(mfs))
|
||||||
return a.zipMediaFiles(ctx, id, format, bitrate, out, mfs)
|
return a.zipMediaFiles(ctx, id, pls.Name, format, bitrate, out, mfs, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *archiver) zipMediaFiles(ctx context.Context, id string, format string, bitrate int, out io.Writer, mfs model.MediaFiles) error {
|
func (a *archiver) zipMediaFiles(ctx context.Context, id, name string, format string, bitrate int, out io.Writer, mfs model.MediaFiles, addM3U bool) error {
|
||||||
z := createZipWriter(out, format, bitrate)
|
z := createZipWriter(out, format, bitrate)
|
||||||
|
|
||||||
|
zippedMfs := make(model.MediaFiles, len(mfs))
|
||||||
for idx, mf := range mfs {
|
for idx, mf := range mfs {
|
||||||
file := a.playlistFilename(mf, format, idx)
|
file := a.playlistFilename(mf, format, idx)
|
||||||
_ = a.addFileToZip(ctx, z, mf, format, bitrate, file)
|
_ = a.addFileToZip(ctx, z, mf, format, bitrate, file)
|
||||||
|
mf.Path = file
|
||||||
|
zippedMfs[idx] = mf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add M3U file if requested
|
||||||
|
if addM3U && len(zippedMfs) > 0 {
|
||||||
|
plsName := sanitizeName(name)
|
||||||
|
w, err := z.CreateHeader(&zip.FileHeader{
|
||||||
|
Name: plsName + ".m3u",
|
||||||
|
Modified: mfs[0].UpdatedAt,
|
||||||
|
Method: zip.Store,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error(ctx, "Error creating playlist zip entry", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte(zippedMfs.ToM3U8(plsName, false)))
|
||||||
|
if err != nil {
|
||||||
|
log.Error(ctx, "Error writing m3u in zip", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := z.Close()
|
err := z.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(ctx, "Error closing zip file", "id", id, err)
|
log.Error(ctx, "Error closing zip file", "id", id, err)
|
||||||
|
|||||||
+13
-1
@@ -145,9 +145,21 @@ var _ = Describe("Archiver", func() {
|
|||||||
zr, err := zip.NewReader(bytes.NewReader(out.Bytes()), int64(out.Len()))
|
zr, err := zip.NewReader(bytes.NewReader(out.Bytes()), int64(out.Len()))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
Expect(len(zr.File)).To(Equal(2))
|
Expect(len(zr.File)).To(Equal(3))
|
||||||
Expect(zr.File[0].Name).To(Equal("01 - AC_DC - track1.mp3"))
|
Expect(zr.File[0].Name).To(Equal("01 - AC_DC - track1.mp3"))
|
||||||
Expect(zr.File[1].Name).To(Equal("02 - Artist 2 - track2.mp3"))
|
Expect(zr.File[1].Name).To(Equal("02 - Artist 2 - track2.mp3"))
|
||||||
|
Expect(zr.File[2].Name).To(Equal("Test Playlist.m3u"))
|
||||||
|
|
||||||
|
// Verify M3U content
|
||||||
|
m3uFile, err := zr.File[2].Open()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
defer m3uFile.Close()
|
||||||
|
|
||||||
|
m3uContent, err := io.ReadAll(m3uFile)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
expectedM3U := "#EXTM3U\n#PLAYLIST:Test Playlist\n#EXTINF:0,AC/DC - track1\n01 - AC_DC - track1.mp3\n#EXTINF:0,Artist 2 - track2\n02 - Artist 2 - track2.mp3\n"
|
||||||
|
Expect(string(m3uContent)).To(Equal(expectedM3U))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user