Extracted playlists entry points
This commit is contained in:
@@ -5,11 +5,13 @@ add_library(lmssubsonic SHARED
|
|||||||
impl/entrypoints/MediaAnnotation.cpp
|
impl/entrypoints/MediaAnnotation.cpp
|
||||||
impl/entrypoints/MediaLibraryScanning.cpp
|
impl/entrypoints/MediaLibraryScanning.cpp
|
||||||
impl/entrypoints/MediaRetrieval.cpp
|
impl/entrypoints/MediaRetrieval.cpp
|
||||||
|
impl/entrypoints/Playlists.cpp
|
||||||
impl/entrypoints/Searching.cpp
|
impl/entrypoints/Searching.cpp
|
||||||
impl/entrypoints/UserManagement.cpp
|
impl/entrypoints/UserManagement.cpp
|
||||||
impl/responses/Album.cpp
|
impl/responses/Album.cpp
|
||||||
impl/responses/Artist.cpp
|
impl/responses/Artist.cpp
|
||||||
impl/responses/Bookmark.cpp
|
impl/responses/Bookmark.cpp
|
||||||
|
impl/responses/Playlist.cpp
|
||||||
impl/responses/Song.cpp
|
impl/responses/Song.cpp
|
||||||
impl/responses/User.cpp
|
impl/responses/User.cpp
|
||||||
impl/ProtocolVersion.cpp
|
impl/ProtocolVersion.cpp
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
#include "entrypoints/MediaAnnotation.hpp"
|
#include "entrypoints/MediaAnnotation.hpp"
|
||||||
#include "entrypoints/MediaLibraryScanning.hpp"
|
#include "entrypoints/MediaLibraryScanning.hpp"
|
||||||
#include "entrypoints/MediaRetrieval.hpp"
|
#include "entrypoints/MediaRetrieval.hpp"
|
||||||
|
#include "entrypoints/Playlists.hpp"
|
||||||
#include "entrypoints/Searching.hpp"
|
#include "entrypoints/Searching.hpp"
|
||||||
#include "entrypoints/UserManagement.hpp"
|
#include "entrypoints/UserManagement.hpp"
|
||||||
#include "responses/Artist.hpp"
|
#include "responses/Artist.hpp"
|
||||||
@@ -176,80 +177,7 @@ handlePingRequest(RequestContext& context)
|
|||||||
return Response::createOkResponse(context.serverProtocolVersion);
|
return Response::createOkResponse(context.serverProtocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
Response
|
|
||||||
handleCreatePlaylistRequest(RequestContext& context)
|
|
||||||
{
|
|
||||||
// Optional params
|
|
||||||
const auto id {getParameterAs<TrackListId>(context.parameters, "playlistId")};
|
|
||||||
auto name {getParameterAs<std::string>(context.parameters, "name")};
|
|
||||||
|
|
||||||
std::vector<TrackId> trackIds {getMultiParametersAs<TrackId>(context.parameters, "songId")};
|
|
||||||
|
|
||||||
if (!name && !id)
|
|
||||||
throw RequiredParameterMissingError {"name or id"};
|
|
||||||
|
|
||||||
auto transaction {context.dbSession.createUniqueTransaction()};
|
|
||||||
|
|
||||||
User::pointer user {User::find(context.dbSession, context.userId)};
|
|
||||||
if (!user)
|
|
||||||
throw UserNotAuthorizedError {};
|
|
||||||
|
|
||||||
TrackList::pointer tracklist;
|
|
||||||
if (id)
|
|
||||||
{
|
|
||||||
tracklist = TrackList::find(context.dbSession, *id);
|
|
||||||
if (!tracklist
|
|
||||||
|| tracklist->getUser() != user
|
|
||||||
|| tracklist->getType() != TrackListType::Playlist)
|
|
||||||
{
|
|
||||||
throw RequestedDataNotFoundError {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name)
|
|
||||||
tracklist.modify()->setName(*name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tracklist = context.dbSession.create<TrackList>(*name, TrackListType::Playlist, false, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const TrackId trackId : trackIds)
|
|
||||||
{
|
|
||||||
Track::pointer track {Track::find(context.dbSession, trackId)};
|
|
||||||
if (!track)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
context.dbSession.create<TrackListEntry>(track, tracklist);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response::createOkResponse(context.serverProtocolVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
Response
|
|
||||||
handleDeletePlaylistRequest(RequestContext& context)
|
|
||||||
{
|
|
||||||
TrackListId id {getMandatoryParameterAs<TrackListId>(context.parameters, "id")};
|
|
||||||
|
|
||||||
auto transaction {context.dbSession.createUniqueTransaction()};
|
|
||||||
|
|
||||||
User::pointer user {User::find(context.dbSession, context.userId)};
|
|
||||||
if (!user)
|
|
||||||
throw UserNotAuthorizedError {};
|
|
||||||
|
|
||||||
TrackList::pointer tracklist {TrackList::find(context.dbSession, id)};
|
|
||||||
if (!tracklist
|
|
||||||
|| tracklist->getUser() != user
|
|
||||||
|| tracklist->getType() != TrackListType::Playlist)
|
|
||||||
{
|
|
||||||
throw RequestedDataNotFoundError {};
|
|
||||||
}
|
|
||||||
|
|
||||||
tracklist.remove();
|
|
||||||
|
|
||||||
return Response::createOkResponse(context.serverProtocolVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
Response
|
Response
|
||||||
@@ -717,134 +645,6 @@ handleGetSimilarSongs2Request(RequestContext& context)
|
|||||||
return handleGetSimilarSongsRequestCommon(context, true /* id3 */);
|
return handleGetSimilarSongsRequestCommon(context, true /* id3 */);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
Response::Node
|
|
||||||
tracklistToResponseNode(const TrackList::pointer& tracklist, Session&)
|
|
||||||
{
|
|
||||||
Response::Node playlistNode;
|
|
||||||
|
|
||||||
playlistNode.setAttribute("id", idToString(tracklist->getId()));
|
|
||||||
playlistNode.setAttribute("name", tracklist->getName());
|
|
||||||
playlistNode.setAttribute("songCount", tracklist->getCount());
|
|
||||||
playlistNode.setAttribute("duration", std::chrono::duration_cast<std::chrono::seconds>(tracklist->getDuration()).count());
|
|
||||||
playlistNode.setAttribute("public", tracklist->isPublic());
|
|
||||||
playlistNode.setAttribute("created", reportedDummyDate);
|
|
||||||
playlistNode.setAttribute("owner", tracklist->getUser()->getLoginName());
|
|
||||||
|
|
||||||
return playlistNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
Response
|
|
||||||
handleGetPlaylistRequest(RequestContext& context)
|
|
||||||
{
|
|
||||||
// Mandatory params
|
|
||||||
TrackListId trackListId {getMandatoryParameterAs<TrackListId>(context.parameters, "id")};
|
|
||||||
|
|
||||||
auto transaction {context.dbSession.createSharedTransaction()};
|
|
||||||
|
|
||||||
User::pointer user {User::find(context.dbSession, context.userId)};
|
|
||||||
if (!user)
|
|
||||||
throw UserNotAuthorizedError {};
|
|
||||||
|
|
||||||
TrackList::pointer tracklist {TrackList::find(context.dbSession, trackListId)};
|
|
||||||
if (!tracklist)
|
|
||||||
throw RequestedDataNotFoundError {};
|
|
||||||
|
|
||||||
Response response {Response::createOkResponse(context.serverProtocolVersion)};
|
|
||||||
Response::Node playlistNode {tracklistToResponseNode(tracklist, context.dbSession)};
|
|
||||||
|
|
||||||
auto entries {tracklist->getEntries()};
|
|
||||||
for (const TrackListEntry::pointer& entry : entries)
|
|
||||||
playlistNode.addArrayChild("entry", createSongNode(entry->getTrack(), context.dbSession, user));
|
|
||||||
|
|
||||||
response.addNode("playlist", playlistNode );
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
Response
|
|
||||||
handleGetPlaylistsRequest(RequestContext& context)
|
|
||||||
{
|
|
||||||
auto transaction {context.dbSession.createSharedTransaction()};
|
|
||||||
|
|
||||||
Response response {Response::createOkResponse(context.serverProtocolVersion)};
|
|
||||||
Response::Node& playlistsNode {response.createNode("playlists")};
|
|
||||||
|
|
||||||
TrackList::FindParameters params;
|
|
||||||
params.setUser(context.userId);
|
|
||||||
params.setType(TrackListType::Playlist);
|
|
||||||
|
|
||||||
auto tracklistIds {TrackList::find(context.dbSession, params)};
|
|
||||||
for (const TrackListId trackListId : tracklistIds.results)
|
|
||||||
{
|
|
||||||
const TrackList::pointer trackList {TrackList::find(context.dbSession, trackListId)};
|
|
||||||
playlistsNode.addArrayChild("playlist", tracklistToResponseNode(trackList, context.dbSession));
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
Response
|
|
||||||
handleUpdatePlaylistRequest(RequestContext& context)
|
|
||||||
{
|
|
||||||
// Mandatory params
|
|
||||||
TrackListId id {getMandatoryParameterAs<TrackListId>(context.parameters, "playlistId")};
|
|
||||||
|
|
||||||
// Optional parameters
|
|
||||||
auto name {getParameterAs<std::string>(context.parameters, "name")};
|
|
||||||
auto isPublic {getParameterAs<bool>(context.parameters, "public")};
|
|
||||||
|
|
||||||
std::vector<TrackId> trackIdsToAdd {getMultiParametersAs<TrackId>(context.parameters, "songIdToAdd")};
|
|
||||||
std::vector<std::size_t> trackPositionsToRemove {getMultiParametersAs<std::size_t>(context.parameters, "songIndexToRemove")};
|
|
||||||
|
|
||||||
auto transaction {context.dbSession.createUniqueTransaction()};
|
|
||||||
|
|
||||||
User::pointer user {User::find(context.dbSession, context.userId)};
|
|
||||||
if (!user)
|
|
||||||
throw UserNotAuthorizedError {};
|
|
||||||
|
|
||||||
TrackList::pointer tracklist {TrackList::find(context.dbSession, id)};
|
|
||||||
if (!tracklist
|
|
||||||
|| tracklist->getUser() != user
|
|
||||||
|| tracklist->getType() != TrackListType::Playlist)
|
|
||||||
{
|
|
||||||
throw RequestedDataNotFoundError {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name)
|
|
||||||
tracklist.modify()->setName(*name);
|
|
||||||
|
|
||||||
if (isPublic)
|
|
||||||
tracklist.modify()->setIsPublic(*isPublic);
|
|
||||||
|
|
||||||
{
|
|
||||||
// Remove from end to make indexes stable
|
|
||||||
std::sort(std::begin(trackPositionsToRemove), std::end(trackPositionsToRemove), std::greater<std::size_t>());
|
|
||||||
|
|
||||||
for (std::size_t trackPositionToRemove : trackPositionsToRemove)
|
|
||||||
{
|
|
||||||
auto entry {tracklist->getEntry(trackPositionToRemove)};
|
|
||||||
if (entry)
|
|
||||||
entry.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add tracks
|
|
||||||
for (const TrackId trackIdToAdd : trackIdsToAdd)
|
|
||||||
{
|
|
||||||
Track::pointer track {Track::find(context.dbSession, trackIdToAdd)};
|
|
||||||
if (!track)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
context.dbSession.create<TrackListEntry>(track, tracklist);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response::createOkResponse(context.serverProtocolVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
Response
|
Response
|
||||||
handleNotImplemented(RequestContext&)
|
handleNotImplemented(RequestContext&)
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Playlists.hpp"
|
||||||
|
|
||||||
|
#include "services/database/Session.hpp"
|
||||||
|
#include "services/database/Track.hpp"
|
||||||
|
#include "services/database/TrackList.hpp"
|
||||||
|
#include "services/database/User.hpp"
|
||||||
|
#include "responses/Playlist.hpp"
|
||||||
|
#include "responses/Song.hpp"
|
||||||
|
#include "ParameterParsing.hpp"
|
||||||
|
#include "SubsonicId.hpp"
|
||||||
|
|
||||||
|
namespace API::Subsonic
|
||||||
|
{
|
||||||
|
using namespace Database;
|
||||||
|
|
||||||
|
Response handleGetPlaylistsRequest(RequestContext& context)
|
||||||
|
{
|
||||||
|
auto transaction{ context.dbSession.createSharedTransaction() };
|
||||||
|
|
||||||
|
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||||
|
Response::Node& playlistsNode{ response.createNode("playlists") };
|
||||||
|
|
||||||
|
TrackList::FindParameters params;
|
||||||
|
params.setUser(context.userId);
|
||||||
|
params.setType(TrackListType::Playlist);
|
||||||
|
|
||||||
|
auto tracklistIds{ TrackList::find(context.dbSession, params) };
|
||||||
|
for (const TrackListId trackListId : tracklistIds.results)
|
||||||
|
{
|
||||||
|
const TrackList::pointer trackList{ TrackList::find(context.dbSession, trackListId) };
|
||||||
|
playlistsNode.addArrayChild("playlist", createPlaylistNode(trackList, context.dbSession));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response handleGetPlaylistRequest(RequestContext& context)
|
||||||
|
{
|
||||||
|
// Mandatory params
|
||||||
|
TrackListId trackListId{ getMandatoryParameterAs<TrackListId>(context.parameters, "id") };
|
||||||
|
|
||||||
|
auto transaction{ context.dbSession.createSharedTransaction() };
|
||||||
|
|
||||||
|
User::pointer user{ User::find(context.dbSession, context.userId) };
|
||||||
|
if (!user)
|
||||||
|
throw UserNotAuthorizedError{};
|
||||||
|
|
||||||
|
TrackList::pointer tracklist{ TrackList::find(context.dbSession, trackListId) };
|
||||||
|
if (!tracklist)
|
||||||
|
throw RequestedDataNotFoundError{};
|
||||||
|
|
||||||
|
Response response{ Response::createOkResponse(context.serverProtocolVersion) };
|
||||||
|
Response::Node playlistNode{ createPlaylistNode(tracklist, context.dbSession) };
|
||||||
|
|
||||||
|
auto entries{ tracklist->getEntries() };
|
||||||
|
for (const TrackListEntry::pointer& entry : entries)
|
||||||
|
playlistNode.addArrayChild("entry", createSongNode(entry->getTrack(), context.dbSession, user));
|
||||||
|
|
||||||
|
response.addNode("playlist", playlistNode);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response handleCreatePlaylistRequest(RequestContext& context)
|
||||||
|
{
|
||||||
|
// Optional params
|
||||||
|
const auto id{ getParameterAs<TrackListId>(context.parameters, "playlistId") };
|
||||||
|
auto name{ getParameterAs<std::string>(context.parameters, "name") };
|
||||||
|
|
||||||
|
std::vector<TrackId> trackIds{ getMultiParametersAs<TrackId>(context.parameters, "songId") };
|
||||||
|
|
||||||
|
if (!name && !id)
|
||||||
|
throw RequiredParameterMissingError{ "name or id" };
|
||||||
|
|
||||||
|
auto transaction{ context.dbSession.createUniqueTransaction() };
|
||||||
|
|
||||||
|
User::pointer user{ User::find(context.dbSession, context.userId) };
|
||||||
|
if (!user)
|
||||||
|
throw UserNotAuthorizedError{};
|
||||||
|
|
||||||
|
TrackList::pointer tracklist;
|
||||||
|
if (id)
|
||||||
|
{
|
||||||
|
tracklist = TrackList::find(context.dbSession, *id);
|
||||||
|
if (!tracklist
|
||||||
|
|| tracklist->getUser() != user
|
||||||
|
|| tracklist->getType() != TrackListType::Playlist)
|
||||||
|
{
|
||||||
|
throw RequestedDataNotFoundError{};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
tracklist.modify()->setName(*name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tracklist = context.dbSession.create<TrackList>(*name, TrackListType::Playlist, false, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const TrackId trackId : trackIds)
|
||||||
|
{
|
||||||
|
Track::pointer track{ Track::find(context.dbSession, trackId) };
|
||||||
|
if (!track)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
context.dbSession.create<TrackListEntry>(track, tracklist);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::createOkResponse(context.serverProtocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Response handleUpdatePlaylistRequest(RequestContext& context)
|
||||||
|
{
|
||||||
|
// Mandatory params
|
||||||
|
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.parameters, "playlistId") };
|
||||||
|
|
||||||
|
// Optional parameters
|
||||||
|
auto name{ getParameterAs<std::string>(context.parameters, "name") };
|
||||||
|
auto isPublic{ getParameterAs<bool>(context.parameters, "public") };
|
||||||
|
|
||||||
|
std::vector<TrackId> trackIdsToAdd{ getMultiParametersAs<TrackId>(context.parameters, "songIdToAdd") };
|
||||||
|
std::vector<std::size_t> trackPositionsToRemove{ getMultiParametersAs<std::size_t>(context.parameters, "songIndexToRemove") };
|
||||||
|
|
||||||
|
auto transaction{ context.dbSession.createUniqueTransaction() };
|
||||||
|
|
||||||
|
User::pointer user{ User::find(context.dbSession, context.userId) };
|
||||||
|
if (!user)
|
||||||
|
throw UserNotAuthorizedError{};
|
||||||
|
|
||||||
|
TrackList::pointer tracklist{ TrackList::find(context.dbSession, id) };
|
||||||
|
if (!tracklist
|
||||||
|
|| tracklist->getUser() != user
|
||||||
|
|| tracklist->getType() != TrackListType::Playlist)
|
||||||
|
{
|
||||||
|
throw RequestedDataNotFoundError{};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
tracklist.modify()->setName(*name);
|
||||||
|
|
||||||
|
if (isPublic)
|
||||||
|
tracklist.modify()->setIsPublic(*isPublic);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Remove from end to make indexes stable
|
||||||
|
std::sort(std::begin(trackPositionsToRemove), std::end(trackPositionsToRemove), std::greater<std::size_t>());
|
||||||
|
|
||||||
|
for (std::size_t trackPositionToRemove : trackPositionsToRemove)
|
||||||
|
{
|
||||||
|
auto entry{ tracklist->getEntry(trackPositionToRemove) };
|
||||||
|
if (entry)
|
||||||
|
entry.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add tracks
|
||||||
|
for (const TrackId trackIdToAdd : trackIdsToAdd)
|
||||||
|
{
|
||||||
|
Track::pointer track{ Track::find(context.dbSession, trackIdToAdd) };
|
||||||
|
if (!track)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
context.dbSession.create<TrackListEntry>(track, tracklist);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::createOkResponse(context.serverProtocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Response handleDeletePlaylistRequest(RequestContext& context)
|
||||||
|
{
|
||||||
|
TrackListId id{ getMandatoryParameterAs<TrackListId>(context.parameters, "id") };
|
||||||
|
|
||||||
|
auto transaction{ context.dbSession.createUniqueTransaction() };
|
||||||
|
|
||||||
|
User::pointer user{ User::find(context.dbSession, context.userId) };
|
||||||
|
if (!user)
|
||||||
|
throw UserNotAuthorizedError{};
|
||||||
|
|
||||||
|
TrackList::pointer tracklist{ TrackList::find(context.dbSession, id) };
|
||||||
|
if (!tracklist
|
||||||
|
|| tracklist->getUser() != user
|
||||||
|
|| tracklist->getType() != TrackListType::Playlist)
|
||||||
|
{
|
||||||
|
throw RequestedDataNotFoundError{};
|
||||||
|
}
|
||||||
|
|
||||||
|
tracklist.remove();
|
||||||
|
|
||||||
|
return Response::createOkResponse(context.serverProtocolVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RequestContext.hpp"
|
||||||
|
#include "SubsonicResponse.hpp"
|
||||||
|
|
||||||
|
namespace API::Subsonic
|
||||||
|
{
|
||||||
|
Response handleGetPlaylistsRequest(RequestContext& context);
|
||||||
|
Response handleGetPlaylistRequest(RequestContext& context);
|
||||||
|
Response handleCreatePlaylistRequest(RequestContext& context);
|
||||||
|
Response handleUpdatePlaylistRequest(RequestContext& context);
|
||||||
|
Response handleDeletePlaylistRequest(RequestContext& context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Playlist.hpp"
|
||||||
|
|
||||||
|
#include "services/database/TrackList.hpp"
|
||||||
|
#include "services/database/User.hpp"
|
||||||
|
#include "SubsonicId.hpp"
|
||||||
|
|
||||||
|
namespace API::Subsonic
|
||||||
|
{
|
||||||
|
using namespace Database;
|
||||||
|
|
||||||
|
static const std::string_view reportedDummyDate{ "2000-01-01T00:00:00" };
|
||||||
|
|
||||||
|
Response::Node createPlaylistNode(const TrackList::pointer& tracklist, Session&)
|
||||||
|
{
|
||||||
|
Response::Node playlistNode;
|
||||||
|
|
||||||
|
playlistNode.setAttribute("id", idToString(tracklist->getId()));
|
||||||
|
playlistNode.setAttribute("name", tracklist->getName());
|
||||||
|
playlistNode.setAttribute("songCount", tracklist->getCount());
|
||||||
|
playlistNode.setAttribute("duration", std::chrono::duration_cast<std::chrono::seconds>(tracklist->getDuration()).count());
|
||||||
|
playlistNode.setAttribute("public", tracklist->isPublic());
|
||||||
|
playlistNode.setAttribute("created", reportedDummyDate);
|
||||||
|
playlistNode.setAttribute("owner", tracklist->getUser()->getLoginName());
|
||||||
|
|
||||||
|
return playlistNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "services/database/Object.hpp"
|
||||||
|
#include "SubsonicResponse.hpp"
|
||||||
|
|
||||||
|
namespace Database
|
||||||
|
{
|
||||||
|
class TrackList;
|
||||||
|
class Session;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace API::Subsonic
|
||||||
|
{
|
||||||
|
Response::Node createPlaylistNode(const Database::ObjectPtr<Database::TrackList>& tracklist, Database::Session& session);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user