[windows] Fix MAC Address Discovery
[xbmc.git] / xbmc / filesystem / AudioBookFileDirectory.cpp
blob2ca214c74e3fcf859b22954577479e475002e198
1 /*
2 * Copyright (C) 2014 Arne Morten Kvarving
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSES/README.md for more information.
6 */
8 #include "AudioBookFileDirectory.h"
10 #include "FileItem.h"
11 #include "FileItemList.h"
12 #include "TextureDatabase.h"
13 #include "URL.h"
14 #include "Util.h"
15 #include "cores/FFmpeg.h"
16 #include "filesystem/File.h"
17 #include "guilib/LocalizeStrings.h"
18 #include "music/tags/MusicInfoTag.h"
19 #include "utils/StringUtils.h"
21 using namespace XFILE;
23 static int cfile_file_read(void *h, uint8_t* buf, int size)
25 CFile* pFile = static_cast<CFile*>(h);
26 return pFile->Read(buf, size);
29 static int64_t cfile_file_seek(void *h, int64_t pos, int whence)
31 CFile* pFile = static_cast<CFile*>(h);
32 if(whence == AVSEEK_SIZE)
33 return pFile->GetLength();
34 else
35 return pFile->Seek(pos, whence & ~AVSEEK_FORCE);
38 CAudioBookFileDirectory::~CAudioBookFileDirectory(void)
40 if (m_fctx)
41 avformat_close_input(&m_fctx);
42 if (m_ioctx)
44 av_free(m_ioctx->buffer);
45 av_free(m_ioctx);
49 bool CAudioBookFileDirectory::GetDirectory(const CURL& url,
50 CFileItemList &items)
52 if (!m_fctx && !ContainsFiles(url))
53 return true;
55 std::string title;
56 std::string author;
57 std::string album;
59 AVDictionaryEntry* tag=nullptr;
60 while ((tag = av_dict_get(m_fctx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
62 if (StringUtils::CompareNoCase(tag->key, "title") == 0)
63 title = tag->value;
64 else if (StringUtils::CompareNoCase(tag->key, "album") == 0)
65 album = tag->value;
66 else if (StringUtils::CompareNoCase(tag->key, "artist") == 0)
67 author = tag->value;
70 std::string thumb;
71 if (m_fctx->nb_chapters > 1)
72 thumb = CTextureUtils::GetWrappedImageURL(url.Get(), "music");
74 for (size_t i=0;i<m_fctx->nb_chapters;++i)
76 tag=nullptr;
77 std::string chaptitle = StringUtils::Format(g_localizeStrings.Get(25010), i + 1);
78 std::string chapauthor;
79 std::string chapalbum;
80 while ((tag=av_dict_get(m_fctx->chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
82 if (StringUtils::CompareNoCase(tag->key, "title") == 0)
83 chaptitle = tag->value;
84 else if (StringUtils::CompareNoCase(tag->key, "artist") == 0)
85 chapauthor = tag->value;
86 else if (StringUtils::CompareNoCase(tag->key, "album") == 0)
87 chapalbum = tag->value;
89 CFileItemPtr item(new CFileItem(url.Get(),false));
90 item->GetMusicInfoTag()->SetTrackNumber(i+1);
91 item->GetMusicInfoTag()->SetLoaded(true);
92 item->GetMusicInfoTag()->SetTitle(chaptitle);
93 if (album.empty())
94 item->GetMusicInfoTag()->SetAlbum(title);
95 else if (chapalbum.empty())
96 item->GetMusicInfoTag()->SetAlbum(album);
97 else
98 item->GetMusicInfoTag()->SetAlbum(chapalbum);
99 if (chapauthor.empty())
100 item->GetMusicInfoTag()->SetArtist(author);
101 else
102 item->GetMusicInfoTag()->SetArtist(chapauthor);
104 item->SetLabel(StringUtils::Format("{0:02}. {1} - {2}", i + 1,
105 item->GetMusicInfoTag()->GetAlbum(),
106 item->GetMusicInfoTag()->GetTitle()));
107 item->SetStartOffset(CUtil::ConvertSecsToMilliSecs(m_fctx->chapters[i]->start *
108 av_q2d(m_fctx->chapters[i]->time_base)));
109 item->SetEndOffset(m_fctx->chapters[i]->end * av_q2d(m_fctx->chapters[i]->time_base));
110 int compare = m_fctx->streams[0]->duration * av_q2d(m_fctx->streams[0]->time_base);
111 if (item->GetEndOffset() < 0 || item->GetEndOffset() > compare)
113 if (i < m_fctx->nb_chapters-1)
114 item->SetEndOffset(m_fctx->chapters[i + 1]->start *
115 av_q2d(m_fctx->chapters[i + 1]->time_base));
116 else
117 item->SetEndOffset(compare);
119 item->SetEndOffset(CUtil::ConvertSecsToMilliSecs(item->GetEndOffset()));
120 item->GetMusicInfoTag()->SetDuration(
121 CUtil::ConvertMilliSecsToSecsInt(item->GetEndOffset() - item->GetStartOffset()));
122 item->SetProperty("item_start", item->GetStartOffset());
123 if (!thumb.empty())
124 item->SetArt("thumb", thumb);
125 items.Add(item);
128 return true;
131 bool CAudioBookFileDirectory::Exists(const CURL& url)
133 return CFile::Exists(url) && ContainsFiles(url);
136 bool CAudioBookFileDirectory::ContainsFiles(const CURL& url)
138 CFile file;
139 if (!file.Open(url))
140 return false;
142 uint8_t* buffer = (uint8_t*)av_malloc(32768);
143 m_ioctx = avio_alloc_context(buffer, 32768, 0, &file, cfile_file_read,
144 nullptr, cfile_file_seek);
146 m_fctx = avformat_alloc_context();
147 m_fctx->pb = m_ioctx;
149 if (file.IoControl(IOCTRL_SEEK_POSSIBLE, nullptr) == 0)
150 m_ioctx->seekable = 0;
152 m_ioctx->max_packet_size = 32768;
154 const AVInputFormat* iformat = nullptr;
155 av_probe_input_buffer(m_ioctx, &iformat, url.Get().c_str(), nullptr, 0, 0);
157 bool contains = false;
158 if (avformat_open_input(&m_fctx, url.Get().c_str(), iformat, nullptr) < 0)
160 if (m_fctx)
161 avformat_close_input(&m_fctx);
162 av_free(m_ioctx->buffer);
163 av_free(m_ioctx);
164 return false;
167 contains = m_fctx->nb_chapters > 1;
169 return contains;