You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.1 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#include "config.h"
#include "LocateUri.hxx"
#include "Print.hxx"
#include "PlaylistAny.hxx"
#include "PlaylistSong.hxx"
#include "SongEnumerator.hxx"
#include "SongPrint.hxx"
#include "song/Filter.hxx"
#include "song/DetachedSong.hxx"
#include "song/LightSong.hxx"
#include "input/Error.hxx"
#include "fs/Traits.hxx"
#include "thread/Mutex.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "PlaylistError.hxx"
#include <fmt/format.h>
#include "client/Response.hxx"
static void
playlist_provider_print(Response &r,
const SongLoader &loader,
const char *uri,
SongEnumerator &e,
unsigned start_index,
unsigned end_index,
bool detail) noexcept
{
const auto base_uri = uri != nullptr
? PathTraitsUTF8::GetParent(uri)
: ".";
std::unique_ptr<DetachedSong> song;
for (unsigned i = 0;
i < end_index && (song = e.NextSong()) != nullptr;
++i) {
if (i < start_index) {
/* skip songs before the start index */
continue;
}
if (playlist_check_translate_song(*song, base_uri,
loader) &&
detail)
song_print_info(r, *song);
else
/* fallback if no detail was requested or no
detail was available */
song_print_uri(r, *song);
}
}
static void
playlist_provider_search_print(Response &r,
const SongLoader &loader,
const char *uri,
SongEnumerator &e,
unsigned start_index,
unsigned end_index,
SongFilter *filter) noexcept
{
const auto base_uri = uri != nullptr
? PathTraitsUTF8::GetParent(uri)
: ".";
std::unique_ptr<DetachedSong> song;
unsigned skip = start_index;
unsigned n = end_index - start_index;
unsigned position = 0;
while ((song = e.NextSong()) != nullptr) {
const bool detail = playlist_check_translate_song(*song, base_uri,
loader);
if (!filter->Match(static_cast<LightSong>(*song))) {
++position;
continue;
}
if (skip > 0) {
--skip;
++position;
continue;
}
if (detail) {
song_print_info(r, *song);
r.Fmt("Pos: {}\n", position);
} else
/* fallback if no detail was requested or no
detail was available */
song_print_uri(r, *song);
if (--n == 0)
break;
++position;
}
}
void
playlist_file_print(Response &r, Partition &partition,
const SongLoader &loader,
const LocatedUri &uri,
unsigned start_index,
unsigned end_index,
bool detail,
SongFilter *filter)
try {
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)
throw PlaylistError::NoSuchList();
if (filter == nullptr)
playlist_provider_print(r, loader, uri.canonical_uri, *playlist,
start_index, end_index, detail);
else
playlist_provider_search_print(r, loader, uri.canonical_uri, *playlist,
start_index, end_index, filter);
} catch (...) {
if (IsFileNotFound(std::current_exception()))
throw PlaylistError::NoSuchList();
throw;
}