mirror of
https://github.com/steredbits/pelagia.git
synced 2026-10-17 17:01:33 +02:00
106 lines
3.5 KiB
C++
106 lines
3.5 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2026 steredbits and Pelagia contributors
|
|
#include "api/jellyfin_stream.h"
|
|
|
|
#include "api/jellyfin_urls.h"
|
|
#include "util/log.h"
|
|
#include "util/session_id.h"
|
|
|
|
namespace api {
|
|
|
|
namespace {
|
|
|
|
constexpr long long kTicksPerMs = 10000;
|
|
|
|
} // namespace
|
|
|
|
bool parse_stream_auth_mode(const std::string& text, StreamAuthMode* out) {
|
|
if (text == "both") {
|
|
*out = StreamAuthMode::Both;
|
|
} else if (text == "query") {
|
|
*out = StreamAuthMode::Query;
|
|
} else if (text == "header") {
|
|
*out = StreamAuthMode::Header;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const char* stream_auth_mode_name(StreamAuthMode mode) {
|
|
switch (mode) {
|
|
case StreamAuthMode::Both:
|
|
return "both";
|
|
case StreamAuthMode::Query:
|
|
return "query";
|
|
case StreamAuthMode::Header:
|
|
return "header";
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
player::StreamRequest build_stream_request(const JellyfinClient& client,
|
|
const std::string& item_id, int64_t start_ms,
|
|
const std::string& play_session_id,
|
|
StreamAuthMode mode, const TrackSelection& tracks) {
|
|
player::StreamRequest request;
|
|
const bool with_query = mode != StreamAuthMode::Header;
|
|
const bool with_header = mode != StreamAuthMode::Query;
|
|
const long long ticks = start_ms > 0 ? start_ms * kTicksPerMs : 0;
|
|
request.url = client.stream_url(item_id, ticks, play_session_id, with_query, tracks);
|
|
if (with_header) {
|
|
request.headers = "Authorization: " + client.authorization_header() + "\r\n";
|
|
}
|
|
request.log_url = mask_api_key(request.url);
|
|
return request;
|
|
}
|
|
|
|
JellyfinStreamLocator::JellyfinStreamLocator(const JellyfinClient& client,
|
|
HttpTransport& control, std::string item_id,
|
|
StreamAuthMode mode, const TrackSelection& tracks)
|
|
: client_(client),
|
|
control_(control),
|
|
item_id_(std::move(item_id)),
|
|
mode_(mode),
|
|
tracks_(tracks) {}
|
|
|
|
void JellyfinStreamLocator::set_tracks(const TrackSelection& tracks) {
|
|
std::lock_guard<std::mutex> lock(tracks_mutex_);
|
|
tracks_ = tracks;
|
|
}
|
|
|
|
TrackSelection JellyfinStreamLocator::tracks() const {
|
|
std::lock_guard<std::mutex> lock(tracks_mutex_);
|
|
return tracks_;
|
|
}
|
|
|
|
std::string JellyfinStreamLocator::new_session_id() {
|
|
return util::make_session_id();
|
|
}
|
|
|
|
bool JellyfinStreamLocator::locate(int64_t start_ms, const std::string& session_id,
|
|
player::StreamRequest* out) {
|
|
if (!client_.is_authenticated()) {
|
|
return false;
|
|
}
|
|
*out = build_stream_request(client_, item_id_, start_ms, session_id, mode_, tracks());
|
|
return true;
|
|
}
|
|
|
|
void JellyfinStreamLocator::release(const std::string& session_id) {
|
|
const HttpResponse resp = control_.del(
|
|
build_active_encodings_url(client_.server_url(), client_.device_id(), session_id),
|
|
{{"Authorization", client_.authorization_header()}});
|
|
if (!resp.ok) {
|
|
LOG_WARN("Stopping transcoding of session %.8s... failed: %s",
|
|
session_id.c_str(), resp.error.c_str());
|
|
} else if (resp.status < 200 || resp.status >= 300) {
|
|
LOG_WARN("Stopping transcoding of session %.8s...: HTTP %ld",
|
|
session_id.c_str(), resp.status);
|
|
} else {
|
|
LOG_DEBUG("Transcoding of session %.8s... stopped", session_id.c_str());
|
|
}
|
|
}
|
|
|
|
} // namespace api
|