New command playlistlength
Count the number of songs and their total playtime in the playlist.
This commit is contained in:
parent
c71e586c53
commit
f801f299c9
2
NEWS
2
NEWS
|
@ -10,7 +10,7 @@ ver 0.24 (not yet released)
|
||||||
- show PCRE support in "config" response
|
- show PCRE support in "config" response
|
||||||
- apply Unicode normalization to case-insensitive filter expressions
|
- apply Unicode normalization to case-insensitive filter expressions
|
||||||
- stickers on playlists and some tag types
|
- stickers on playlists and some tag types
|
||||||
- new command "stickernames"
|
- new commands "stickernames" and "playlistlength"
|
||||||
- new "search"/"find" filter "added-since"
|
- new "search"/"find" filter "added-since"
|
||||||
* database
|
* database
|
||||||
- attribute "added" shows when each song was added to the database
|
- attribute "added" shows when each song was added to the database
|
||||||
|
|
|
@ -1001,6 +1001,19 @@ remote playlists (absolute URI with a supported scheme).
|
||||||
|
|
||||||
The second parameter can be a range. [#since_0_23_3]_
|
The second parameter can be a range. [#since_0_23_3]_
|
||||||
|
|
||||||
|
.. _command_playlistlength:
|
||||||
|
|
||||||
|
:command:`playlistlength {NAME}`
|
||||||
|
Count the number of songs and their total playtime (seconds) in the
|
||||||
|
playlist.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
playlistlength example
|
||||||
|
songs: 10
|
||||||
|
playtime: 8192
|
||||||
|
OK
|
||||||
|
|
||||||
.. _command_playlistmove:
|
.. _command_playlistmove:
|
||||||
|
|
||||||
:command:`playlistmove {NAME} [{FROM} | {START:END}] {TO}`
|
:command:`playlistmove {NAME} [{FROM} | {START:END}] {TO}`
|
||||||
|
|
|
@ -387,6 +387,7 @@ sources = [
|
||||||
'src/PlaylistError.cxx',
|
'src/PlaylistError.cxx',
|
||||||
'src/PlaylistPrint.cxx',
|
'src/PlaylistPrint.cxx',
|
||||||
'src/PlaylistSave.cxx',
|
'src/PlaylistSave.cxx',
|
||||||
|
'src/playlist/Length.cxx',
|
||||||
'src/playlist/PlaylistStream.cxx',
|
'src/playlist/PlaylistStream.cxx',
|
||||||
'src/playlist/PlaylistMapper.cxx',
|
'src/playlist/PlaylistMapper.cxx',
|
||||||
'src/playlist/PlaylistAny.cxx',
|
'src/playlist/PlaylistAny.cxx',
|
||||||
|
|
|
@ -148,6 +148,7 @@ static constexpr struct command commands[] = {
|
||||||
{ "playlistfind", PERMISSION_READ, 1, -1, handle_playlistfind },
|
{ "playlistfind", PERMISSION_READ, 1, -1, handle_playlistfind },
|
||||||
{ "playlistid", PERMISSION_READ, 0, 1, handle_playlistid },
|
{ "playlistid", PERMISSION_READ, 0, 1, handle_playlistid },
|
||||||
{ "playlistinfo", PERMISSION_READ, 0, 1, handle_playlistinfo },
|
{ "playlistinfo", PERMISSION_READ, 0, 1, handle_playlistinfo },
|
||||||
|
{ "playlistlength", PERMISSION_READ, 1, 1, handle_playlistlength },
|
||||||
{ "playlistmove", PERMISSION_CONTROL, 3, 3, handle_playlistmove },
|
{ "playlistmove", PERMISSION_CONTROL, 3, 3, handle_playlistmove },
|
||||||
{ "playlistsearch", PERMISSION_READ, 1, -1, handle_playlistsearch },
|
{ "playlistsearch", PERMISSION_READ, 1, -1, handle_playlistsearch },
|
||||||
{ "plchanges", PERMISSION_READ, 1, 2, handle_plchanges },
|
{ "plchanges", PERMISSION_READ, 1, 2, handle_plchanges },
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "SongLoader.hxx"
|
#include "SongLoader.hxx"
|
||||||
#include "song/DetachedSong.hxx"
|
#include "song/DetachedSong.hxx"
|
||||||
#include "BulkEdit.hxx"
|
#include "BulkEdit.hxx"
|
||||||
|
#include "playlist/Length.hxx"
|
||||||
#include "playlist/PlaylistQueue.hxx"
|
#include "playlist/PlaylistQueue.hxx"
|
||||||
#include "playlist/Print.hxx"
|
#include "playlist/Print.hxx"
|
||||||
#include "TimePrint.hxx"
|
#include "TimePrint.hxx"
|
||||||
|
@ -149,6 +150,23 @@ handle_listplaylistinfo(Client &client, Request args, Response &r)
|
||||||
throw PlaylistError::NoSuchList();
|
throw PlaylistError::NoSuchList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandResult
|
||||||
|
handle_playlistlength(Client &client, Request args, Response &r)
|
||||||
|
{
|
||||||
|
const auto name = LocateUri(UriPluginKind::PLAYLIST, args.front(),
|
||||||
|
&client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, nullptr
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
if (playlist_file_length(r, client.GetPartition(), SongLoader(client),
|
||||||
|
name))
|
||||||
|
return CommandResult::OK;
|
||||||
|
|
||||||
|
throw PlaylistError::NoSuchList();
|
||||||
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_rm([[maybe_unused]] Client &client, Request args, [[maybe_unused]] Response &r)
|
handle_rm([[maybe_unused]] Client &client, Request args, [[maybe_unused]] Response &r)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,9 @@ handle_listplaylist(Client &client, Request request, Response &response);
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listplaylistinfo(Client &client, Request request, Response &response);
|
handle_listplaylistinfo(Client &client, Request request, Response &response);
|
||||||
|
|
||||||
|
CommandResult
|
||||||
|
handle_playlistlength(Client &client, Request request, Response &response);
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_rm(Client &client, Request request, Response &response);
|
handle_rm(Client &client, Request request, Response &response);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
// Copyright The Music Player Daemon Project
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "LocateUri.hxx"
|
||||||
|
#include "Length.hxx"
|
||||||
|
#include "PlaylistAny.hxx"
|
||||||
|
#include "PlaylistSong.hxx"
|
||||||
|
#include "SongEnumerator.hxx"
|
||||||
|
#include "SongPrint.hxx"
|
||||||
|
#include "song/DetachedSong.hxx"
|
||||||
|
#include "song/LightSong.hxx"
|
||||||
|
#include "fs/Traits.hxx"
|
||||||
|
#include "thread/Mutex.hxx"
|
||||||
|
#include "Partition.hxx"
|
||||||
|
#include "Instance.hxx"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
static SignedSongTime get_duration(const DetachedSong &song) {
|
||||||
|
const auto duration = song.GetDuration();
|
||||||
|
return duration.IsNegative() ? (SignedSongTime)0 : song.GetDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
playlist_provider_length(Response &r,
|
||||||
|
const SongLoader &loader,
|
||||||
|
const char *uri,
|
||||||
|
SongEnumerator &e) noexcept
|
||||||
|
{
|
||||||
|
const auto base_uri = uri != nullptr
|
||||||
|
? PathTraitsUTF8::GetParent(uri)
|
||||||
|
: ".";
|
||||||
|
|
||||||
|
std::unique_ptr<DetachedSong> song;
|
||||||
|
unsigned i = 0;
|
||||||
|
SignedSongTime playtime = (SignedSongTime)0;
|
||||||
|
while ((song = e.NextSong()) != nullptr) {
|
||||||
|
if (playlist_check_translate_song(*song, base_uri,
|
||||||
|
loader))
|
||||||
|
playtime += get_duration(*song);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
r.Fmt(FMT_STRING("songs: {}\n"), i);
|
||||||
|
r.Fmt(FMT_STRING("playtime: {}\n"), playtime.RoundS());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
playlist_file_length(Response &r, Partition &partition,
|
||||||
|
const SongLoader &loader,
|
||||||
|
const LocatedUri &uri)
|
||||||
|
{
|
||||||
|
Mutex mutex;
|
||||||
|
|
||||||
|
#ifndef ENABLE_DATABASE
|
||||||
|
(void)partition;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto playlist = playlist_open_any(uri,
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
partition.instance.storage,
|
||||||
|
#endif
|
||||||
|
mutex);
|
||||||
|
if (playlist == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
playlist_provider_length(r, loader, uri.canonical_uri, *playlist);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
// Copyright The Music Player Daemon Project
|
||||||
|
|
||||||
|
#ifndef MPD_PLAYLIST__LENGTH_HXX
|
||||||
|
#define MPD_PLAYLIST__LENGTH_HXX
|
||||||
|
|
||||||
|
#include "client/Response.hxx"
|
||||||
|
|
||||||
|
class SongLoader;
|
||||||
|
struct Partition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of songs and their total playtime (seconds) in the
|
||||||
|
* playlist.
|
||||||
|
*
|
||||||
|
* @param uri the URI of the playlist file in UTF-8 encoding
|
||||||
|
* @return true on success, false if the playlist does not exist
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
playlist_file_length(Response &r, Partition &partition,
|
||||||
|
const SongLoader &loader,
|
||||||
|
const LocatedUri &uri);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue