Skip to content

Commit

Permalink
Merge branch 'countplaylist' of https://github.com/jcorporation/MPD
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Feb 15, 2024
2 parents 7f18cae + f801f29 commit 9eb26ab
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 1 deletion.
2 changes: 1 addition & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions doc/protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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}`
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions src/command/AllCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
18 changes: 18 additions & 0 deletions src/command/PlaylistCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
{
Expand Down
3 changes: 3 additions & 0 deletions src/command/PlaylistCommands.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
69 changes: 69 additions & 0 deletions src/playlist/Length.cxx
Original file line number Diff line number Diff line change
@@ -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;
}
24 changes: 24 additions & 0 deletions src/playlist/Length.hxx
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 9eb26ab

Please sign in to comment.