Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/control/upnp_server/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 8 kB image not shown  

Quelle  FileHandler.cpp   Sprache: C

 

/*****************************************************************************
 * FileHandler.cpp
 *****************************************************************************
 * Copyright © 2024 VLC authors and VideoLAN
 *
 * Authors: Alaric Senat <alaric@videolabs.io>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <ctime>
#include <sstream>

#include <vlc_common.h>

#include <vlc_addons.h>
#include <vlc_cxx_helpers.hpp>
#include <vlc_fourcc.h>
#include <vlc_interface.h>
#include <vlc_player.h>
#include <vlc_rand.h>
#include <vlc_stream.h>
#include <vlc_stream_extractor.h>
#include <vlc_url.h>

#include "FileHandler.hpp"
#include "ml.hpp"
#include "utils.hpp"

// static constexpr char DLNA_TRANSFER_MODE[] = "transfermode.dlna.org";
static constexpr char DLNA_CONTENT_FEATURE[] = "contentfeatures.dlna.org";
// static constexpr char DLNA_TIME_SEEK_RANGE[] = "timeseekrange.dlna.org";

/// Convenient C++ replacement of vlc_ml_file_t to not have to deal with allocations
struct MLFile
{
    std::string mrl;
    int64_t size;
    time_t last_modification;
};

/// Usual filesystem FileHandler implementation, this is the most commonly used FileHandler, for
/// non-transcoded local medias, thumbnails and subs.
class MLFileHandler : public FileHandler
{
  public:
    MLFile file;
    utils::MimeType mime_type;

    std::unique_ptr<stream_t, decltype(&vlc_stream_Delete)> stream = {nullptr, &vlc_stream_Delete};

    MLFileHandler(MLFile &&file, utils::MimeType &&mime_type) :
        file(std::move(file)),
        mime_type(std::move(mime_type))
    {}

    bool get_info(UpnpFileInfo &info) final
    {
        UpnpFileInfo_set_ContentType(&info, mime_type.combine().c_str());
        UpnpFileInfo_set_FileLength(&info, file.size);
        UpnpFileInfo_set_LastModified(&info, file.last_modification);

        // const_cast is expected by the design of the upnp api as it only serves const list heads
        // FIXME: see if there's no way to patch that in libupnp, we shouldn't have to break const
        // to do something so usual.
        auto *head = const_cast<UpnpListHead *>(UpnpFileInfo_get_ExtraHeadersList(&info));
        utils::http::add_response_hdr(head, {DLNA_CONTENT_FEATURE, "DLNA.ORG_OP=01"});
        return true;
    }

    bool open(vlc_object_t *parent) final
    {
        stream = vlc::wrap_cptr(vlc_stream_NewMRL(parent, file.mrl.c_str()), &vlc_stream_Delete);
        return stream != nullptr;
    }

    size_t read(uint8_t buffer[], size_t buffer_len) noexcept final
    {
        return vlc_stream_Read(stream.get(), buffer, buffer_len);
    }

    bool seek(SeekType type, off_t offset) noexcept final
    {
        uint64_t real_offset;
        switch (type)
        {
            case SeekType::Current:
                real_offset = vlc_stream_Tell(stream.get()) + offset;
                break;
            case SeekType::End:
                if (vlc_stream_GetSize(stream.get(), &real_offset) != VLC_SUCCESS)
                {
                    return false;
                }
                real_offset += offset;
                break;
            case SeekType::Set:
                real_offset = offset;
                break;
            default:
                return false;
        }

        return vlc_stream_Seek(stream.get(), real_offset) == 0;
    }
};

//
// Url parsing and FileHandler Factory
//

template <typename MLHelper>
auto get_ml_object(const std::string &token,
                   std::string &extension,
                   const ml::MediaLibraryContext &ml)
{
    const auto extension_idx = token.find('.');
    extension = token.substr(extension_idx + 1);

    try
    {
        const int64_t ml_id = std::stoll(token.substr(0, extension_idx));
        return MLHelper::get(ml, ml_id);
    }
    catch (const std::exception &)
    {
        return typename MLHelper::Ptr{nullptr, nullptr};
    }
}

static std::unique_ptr<FileHandler> parse_media_url(std::stringstream &ss,
                                                    const ml::MediaLibraryContext &ml)
{
    std::string token;
    std::getline(ss, token, '/');

    if (token != "native")
    {
        // TODO Select a transcode profile
    }

    std::getline(ss, token);

    std::string extension;
    const auto media = get_ml_object<ml::Media>(token, extension, ml);
    if (media == nullptr)
    {
        return nullptr;
    }

    const auto main_files = utils::get_media_files(*media, VLC_ML_FILE_TYPE_MAIN);
    if (main_files.empty())
    {
        return nullptr;
    }
    const vlc_ml_file_t &main_file = main_files.front();

    auto mime_type = utils::get_mimetype(media->i_type, extension);
    auto ret = std::make_unique<MLFileHandler>(
        MLFile{main_file.psz_mrl, main_file.i_size, main_file.i_last_modification_date},
        std::move(mime_type));
    return ret;
}

static std::unique_ptr<FileHandler> parse_thumbnail_url(std::stringstream &ss,
                                                        const ml::MediaLibraryContext &ml)
{
    std::string token;
    std::getline(ss, token, '/');
    vlc_ml_thumbnail_size_t size;
    if (token == "small")
        size = VLC_ML_THUMBNAIL_SMALL;
    else if (token == "banner")
        size = VLC_ML_THUMBNAIL_BANNER;
    else
        return nullptr;

    std::getline(ss, token, '/');
    std::string extension;
    std::string mrl;
    if (token == "media")
    {
        std::getline(ss, token);
        const auto media = get_ml_object<ml::Media>(token, extension, ml);
        if (media && media->thumbnails[size].i_status == VLC_ML_THUMBNAIL_STATUS_AVAILABLE)
            mrl = media->thumbnails[size].psz_mrl;
    }
    else if (token == "album")
    {
        std::getline(ss, token);
        const auto album = get_ml_object<ml::Album>(token, extension, ml);
        if (album && album->thumbnails[size].i_status == VLC_ML_THUMBNAIL_STATUS_AVAILABLE)
            mrl = album->thumbnails[size].psz_mrl;
    }

    if (mrl.empty())
    {
        return nullptr;
    }

    return std::make_unique<MLFileHandler>(MLFile{mrl, -1, 0}, utils::MimeType{"image", extension});
}

static std::unique_ptr<FileHandler> parse_subtitle_url(std::stringstream &ss,
                                                       const ml::MediaLibraryContext &ml)
{
    std::string token;
    std::string extension;
    std::string mrl;

    std::getline(ss, token);
    const auto media = get_ml_object<ml::Media>(token, extension, ml);
    if (media == nullptr)
    {
        return nullptr;
    }

    const auto subtitles = utils::get_media_files(*media, VLC_ML_FILE_TYPE_SUBTITLE);
    if (subtitles.empty())
    {
        return nullptr;
    }

    const vlc_ml_file_t &sub = subtitles.front();
    return std::make_unique<MLFileHandler>(
        MLFile{sub.psz_mrl, sub.i_size, sub.i_last_modification_date},
        utils::MimeType{"text", extension});
}

std::unique_ptr<FileHandler> parse_url(const char *url, const ml::MediaLibraryContext &ml)
{
    std::stringstream ss(url);

    std::string token;
    std::getline(ss, token, '/');
    if (!token.empty())
        return nullptr;

    std::getline(ss, token, '/');
    if (token == "media")
        return parse_media_url(ss, ml);
    else if (token == "thumbnail")
        return parse_thumbnail_url(ss, ml);
    else if (token == "subtitle")
        return parse_subtitle_url(ss, ml);
    return nullptr;
}

Messung
CHZG
83999592

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.