Merge branch 'countplaylist' of https://github.com/jcorporation/MPD
This commit is contained in:
commit
9eb26ab90c
2
NEWS
2
NEWS
|
@ -10,7 +10,7 @@ ver 0.24 (not yet released)
|
|||
- show PCRE support in "config" response
|
||||
- apply Unicode normalization to case-insensitive filter expressions
|
||||
- stickers on playlists and some tag types
|
||||
- new command "stickernames"
|
||||
- new commands "stickernames" and "playlistlength"
|
||||
- new "search"/"find" filter "added-since"
|
||||
- allow range in listplaylist and listplaylistinfo
|
||||
* database
|
||||
|
|
|
@ -1003,6 +1003,19 @@ remote playlists (absolute URI with a supported scheme).
|
|||
|
||||
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 {NAME} [{FROM} | {START:END}] {TO}`
|
||||
|
|
|
@ -387,6 +387,7 @@ sources = [
|
|||
'src/PlaylistError.cxx',
|
||||
'src/PlaylistPrint.cxx',
|
||||
'src/PlaylistSave.cxx',
|
||||
'src/playlist/Length.cxx',
|
||||
'src/playlist/PlaylistStream.cxx',
|
||||
'src/playlist/PlaylistMapper.cxx',
|
||||
'src/playlist/PlaylistAny.cxx',
|
||||
|
|
|
@ -148,6 +148,7 @@ static constexpr struct command commands[] = {
|
|||
{ "playlistfind", PERMISSION_READ, 1, -1, handle_playlistfind },
|
||||
{ "playlistid", PERMISSION_READ, 0, 1, handle_playlistid },
|
||||
{ "playlistinfo", PERMISSION_READ, 0, 1, handle_playlistinfo },
|
||||
{ "playlistlength", PERMISSION_READ, 1, 1, handle_playlistlength },
|
||||
{ "playlistmove", PERMISSION_CONTROL, 3, 3, handle_playlistmove },
|
||||
{ "playlistsearch", PERMISSION_READ, 1, -1, handle_playlistsearch },
|
||||
{ "plchanges", PERMISSION_READ, 1, 2, handle_plchanges },
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "SongLoader.hxx"
|
||||
#include "song/DetachedSong.hxx"
|
||||
#include "BulkEdit.hxx"
|
||||
#include "playlist/Length.hxx"
|
||||
#include "playlist/PlaylistQueue.hxx"
|
||||
#include "playlist/Print.hxx"
|
||||
#include "TimePrint.hxx"
|
||||
|
@ -153,6 +154,23 @@ handle_listplaylistinfo(Client &client, Request args, Response &r)
|
|||
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
|
||||
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
|
||||
handle_listplaylistinfo(Client &client, Request request, Response &response);
|
||||
|
||||
CommandResult
|
||||
handle_playlistlength(Client &client, Request request, Response &response);
|
||||
|
||||
CommandResult
|
||||
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