From c04dcc2e7d834218ef2d4194331e383402495ae1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 20:07:22 +0200 Subject: Adding upstream version 2:20.4+dfsg. Signed-off-by: Daniel Baumann --- xbmc/filesystem/AudioBookFileDirectory.cpp | 168 +++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 xbmc/filesystem/AudioBookFileDirectory.cpp (limited to 'xbmc/filesystem/AudioBookFileDirectory.cpp') diff --git a/xbmc/filesystem/AudioBookFileDirectory.cpp b/xbmc/filesystem/AudioBookFileDirectory.cpp new file mode 100644 index 0000000..04d1c14 --- /dev/null +++ b/xbmc/filesystem/AudioBookFileDirectory.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014 Arne Morten Kvarving + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "AudioBookFileDirectory.h" + +#include "FileItem.h" +#include "TextureDatabase.h" +#include "URL.h" +#include "Util.h" +#include "filesystem/File.h" +#include "guilib/LocalizeStrings.h" +#include "music/tags/MusicInfoTag.h" +#include "utils/StringUtils.h" + +using namespace XFILE; + +static int cfile_file_read(void *h, uint8_t* buf, int size) +{ + CFile* pFile = static_cast(h); + return pFile->Read(buf, size); +} + +static int64_t cfile_file_seek(void *h, int64_t pos, int whence) +{ + CFile* pFile = static_cast(h); + if(whence == AVSEEK_SIZE) + return pFile->GetLength(); + else + return pFile->Seek(pos, whence & ~AVSEEK_FORCE); +} + +CAudioBookFileDirectory::~CAudioBookFileDirectory(void) +{ + if (m_fctx) + avformat_close_input(&m_fctx); + if (m_ioctx) + { + av_free(m_ioctx->buffer); + av_free(m_ioctx); + } +} + +bool CAudioBookFileDirectory::GetDirectory(const CURL& url, + CFileItemList &items) +{ + if (!m_fctx && !ContainsFiles(url)) + return true; + + std::string title; + std::string author; + std::string album; + + AVDictionaryEntry* tag=nullptr; + while ((tag = av_dict_get(m_fctx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) + { + if (StringUtils::CompareNoCase(tag->key, "title") == 0) + title = tag->value; + else if (StringUtils::CompareNoCase(tag->key, "album") == 0) + album = tag->value; + else if (StringUtils::CompareNoCase(tag->key, "artist") == 0) + author = tag->value; + } + + std::string thumb; + if (m_fctx->nb_chapters > 1) + thumb = CTextureUtils::GetWrappedImageURL(url.Get(), "music"); + + for (size_t i=0;inb_chapters;++i) + { + tag=nullptr; + std::string chaptitle = StringUtils::Format(g_localizeStrings.Get(25010), i + 1); + std::string chapauthor; + std::string chapalbum; + while ((tag=av_dict_get(m_fctx->chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) + { + if (StringUtils::CompareNoCase(tag->key, "title") == 0) + chaptitle = tag->value; + else if (StringUtils::CompareNoCase(tag->key, "artist") == 0) + chapauthor = tag->value; + else if (StringUtils::CompareNoCase(tag->key, "album") == 0) + chapalbum = tag->value; + } + CFileItemPtr item(new CFileItem(url.Get(),false)); + item->GetMusicInfoTag()->SetTrackNumber(i+1); + item->GetMusicInfoTag()->SetLoaded(true); + item->GetMusicInfoTag()->SetTitle(chaptitle); + if (album.empty()) + item->GetMusicInfoTag()->SetAlbum(title); + else if (chapalbum.empty()) + item->GetMusicInfoTag()->SetAlbum(album); + else + item->GetMusicInfoTag()->SetAlbum(chapalbum); + if (chapauthor.empty()) + item->GetMusicInfoTag()->SetArtist(author); + else + item->GetMusicInfoTag()->SetArtist(chapauthor); + + item->SetLabel(StringUtils::Format("{0:02}. {1} - {2}", i + 1, + item->GetMusicInfoTag()->GetAlbum(), + item->GetMusicInfoTag()->GetTitle())); + item->SetStartOffset(CUtil::ConvertSecsToMilliSecs(m_fctx->chapters[i]->start * + av_q2d(m_fctx->chapters[i]->time_base))); + item->SetEndOffset(m_fctx->chapters[i]->end * av_q2d(m_fctx->chapters[i]->time_base)); + int compare = m_fctx->duration / (AV_TIME_BASE); + if (item->GetEndOffset() < 0 || item->GetEndOffset() > compare) + { + if (i < m_fctx->nb_chapters-1) + item->SetEndOffset(m_fctx->chapters[i + 1]->start * + av_q2d(m_fctx->chapters[i + 1]->time_base)); + else + item->SetEndOffset(compare); + } + item->SetEndOffset(CUtil::ConvertSecsToMilliSecs(item->GetEndOffset())); + item->GetMusicInfoTag()->SetDuration( + CUtil::ConvertMilliSecsToSecsInt(item->GetEndOffset() - item->GetStartOffset())); + item->SetProperty("item_start", item->GetStartOffset()); + if (!thumb.empty()) + item->SetArt("thumb", thumb); + items.Add(item); + } + + return true; +} + +bool CAudioBookFileDirectory::Exists(const CURL& url) +{ + return CFile::Exists(url) && ContainsFiles(url); +} + +bool CAudioBookFileDirectory::ContainsFiles(const CURL& url) +{ + CFile file; + if (!file.Open(url)) + return false; + + uint8_t* buffer = (uint8_t*)av_malloc(32768); + m_ioctx = avio_alloc_context(buffer, 32768, 0, &file, cfile_file_read, + nullptr, cfile_file_seek); + + m_fctx = avformat_alloc_context(); + m_fctx->pb = m_ioctx; + + if (file.IoControl(IOCTRL_SEEK_POSSIBLE, nullptr) == 0) + m_ioctx->seekable = 0; + + m_ioctx->max_packet_size = 32768; + + AVInputFormat* iformat=nullptr; + av_probe_input_buffer(m_ioctx, &iformat, url.Get().c_str(), nullptr, 0, 0); + + bool contains = false; + if (avformat_open_input(&m_fctx, url.Get().c_str(), iformat, nullptr) < 0) + { + if (m_fctx) + avformat_close_input(&m_fctx); + av_free(m_ioctx->buffer); + av_free(m_ioctx); + return false; + } + + contains = m_fctx->nb_chapters > 1; + + return contains; +} -- cgit v1.2.3