【发布时间】:2019-08-21 06:34:05
【问题描述】:
我正在尝试在 qt/c++ 中创建自己的音乐播放器/库。
我已经完成的是扫描音乐文件的文件夹,使用 taglib 读取音乐文件的标签,从文件中创建一个 Track 结构,并将 Track 放入 @ 987654325@ 的曲目。这是我到目前为止的代码:
这会扫描文件夹:
void LibraryScanner::scanFolder (std::string scanFolder) {
if (filesystem::exists (scanFolder) && filesystem::is_directory (scanFolder))
{
filesystem::recursive_directory_iterator recursiveIterator (scanFolder);
for (const auto& entry : filesystem::recursive_directory_iterator (scanFolder)) {
std::wstring path = entry.path().wstring ();
if (hasEnding (path, L".flac") || hasEnding (path, L".wav") || hasEnding (path, L".alac") || hasEnding (path, L".mp3") || hasEnding (path, L".m4a") || hasEnding (path, L".wma") || hasEnding (path, L".opus") || hasEnding (path, L".ogg") || hasEnding (path, L".aiff")) { ///TODO: ignore capital letters
scanFile (path);
}
}
}
}
每个音频文件然后在 scanFile 方法中进一步处理:
void LibraryScanner::scanFile (const std::wstring filePath)
{
Track track = Track ();
TagLib::FileRef f (filePath.c_str());
if(!f.isNull()){
track.filePath = filePath.c_str ();
track.Title = f.tag()->title().toWString();
track.Artists = f.tag()->artist().toWString();
tracks.push_back (track);
}else {
std::wcout << "File is null." << '\n';
}
}
每条轨道都放入这个向量中:
std::vector<Track> tracks;
这是Track 结构:
#pragma once
#include<string>
struct Track{
std::wstring filePath, Title, Artists;
};
所以现在,我希望我的音乐播放器能够像这样工作:
有一个按字母顺序排序的艺术家列表(图片左侧),每个艺术家都有不同的曲目(右侧),这些曲目也按他们的专辑排序。
我还应该注意,每个曲目可以有多个艺术家,因此 2 个艺术家可以共享相同的曲目。
而且,我不仅可以按艺术家排序,还可以按专辑或其他标签排序(您可以在第二张图片中看到)。在这个程序中可以立即在按艺术家/专辑排序之间切换。
那么我如何在我自己的程序中实现这样的东西,它也非常高效?
我正在考虑在扫描期间对所有内容进行预分类。所以在我将每个Track 放入Tracks 的vector 之后,我创建了一个vector 或Set 的Artists,每个艺术家都包含曲目或专辑。所以我创建了一个像这样的Artist 结构:
#pragma once
#include <vector>
#include "Track.h"
#include <string>
class Artist
{
public:
Artist (std::wstring artistName);
~Artist ();
std::wstring artistName;
std::vector<Track*> tracks;
};
由于多个艺术家可以共享曲目,我认为让曲目矢量只包含 Track 的指针是个好主意。
所以我预先排序的艺术家列表将是std::vector<Artist> artists;,并且每个艺术家都包含自己的具有相同艺术家标签的曲目(稍后我可以按专辑排序)。
然后,如果我想按专辑排序,我有另一个像这样的向量:std::vector<Album> albums;,每个 Album 都包含自己的曲目。
如果我想切换排序模式,我只需更改哪个向量显示为列表即可。
我的问题是,是否有更高效/更高效的方式来完成这一切。 这看起来会占用大量内存并且需要花费大量时间进行排序,因为我基本上会在扫描后进行多次排序(每种排序模式一个向量)。
另外,我需要检查是否有重复的艺术家。另外,每个曲目/艺术家/专辑都应该有一个我想要显示的封面图片。我也需要检查那些重复项
所以这种方式会占用大量资源。 如果有人知道如何有效地做到这一点,我将非常感激,并且也许也有一些代码示例。 如果有人知道一种更高效的方式来扫描文件夹中的文件或我在发布的代码 sn-ps 中所做的事情,那也会有所帮助。
谢谢!
【问题讨论】:
-
也许你想为你的数据使用 sqlite。
-
由于多个艺术家可以共享曲目 -- 建议使用
std::vector<std::shared_ptr<Track>>而不是std::vector<Track*>