C++ 创建分类音乐库的有效方法
我正在尝试用qt/c++创建一个自己的音乐播放器/库。 我已经做的是扫描一个文件夹中的音乐文件,用taglib读取音乐文件的标签,从文件中创建一个C++ 创建分类音乐库的有效方法,c++,qt,sorting,vector,set,C++,Qt,Sorting,Vector,Set,我正在尝试用qt/c++创建一个自己的音乐播放器/库。 我已经做的是扫描一个文件夹中的音乐文件,用taglib读取音乐文件的标签,从文件中创建一个Trackstruct,并将Track放在一个矢量的曲目中。以下是我目前掌握的代码: 这将扫描文件夹: void LibraryScanner::scanFolder (std::string scanFolder) { if (filesystem::exists (scanFolder) && filesystem::is_
Track
struct,并将Track
放在一个矢量的曲目中。以下是我目前掌握的代码:
这将扫描文件夹:
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';
}
}
现在,我想让我的音乐播放器像这样工作:
#pragma once
#include <vector>
#include "Track.h"
#include <string>
class Artist
{
public:
Artist (std::wstring artistName);
~Artist ();
std::wstring artistName;
std::vector<Track*> tracks;
};
有一个按字母顺序排序的艺术家列表(图片左侧),每个艺术家都有不同的曲目(右侧),这些曲目也按他们的专辑排序
我还应该注意到,每首曲目可以有多个艺术家,因此两位艺术家可以共享同一首曲目
而且,我不仅可以按艺术家排序,还可以按唱片集或其他标签排序(你可以在第二张图中看到)。在这个程序中,可以立即切换按艺术家/专辑排序
那么,我如何在我自己的程序中实现这样的东西,这也是非常有效的?
我想在扫描过程中对所有内容进行预排序。因此,在我将每个曲目
放入曲目的向量
之后,我创建了一个向量
或艺术家集
,每个艺术家都包含曲目或专辑。所以我创建了一个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;
};
#pragma一次
#包括
#包括“Track.h”
#包括
班主任
{
公众:
艺术家(std::wstring artistName);
~艺术家();
std::wstring艺人姓名;
矢量轨迹;
};
由于多个艺术家可以共享轨迹,我认为让轨迹向量只包含Track
的指针是个好主意
所以我预先分类的艺术家名单将是一个std::vector艺术家代码>,每个艺人都包含自己的曲目,带有相同的艺人标签(稍后我可以按专辑排序)
然后,如果我想按相册排序,我有另一个向量像这样:std::vector albums代码>与每个包含自己曲目的相册
。
如果我想切换排序模式,我只需要改变哪个向量显示为列表
我的问题是,是否有一种更高效的方式来实现这一切。
这看起来会占用大量内存,需要花费大量时间进行排序,因为我基本上会在扫描后进行多次排序(对于每个排序模式,一个向量)
另外,我需要检查是否有重复的艺术家。另外,每首曲目/艺术家/专辑都应该有自己的封面图片,我想展示。我也需要检查一下那些有没有重复的
因此,这种方法将使用大量资源。
如果有人知道如何有效地实现这一点,我会非常感激,也许还有一些代码示例。
如果有人知道一种更高效的方法来扫描文件夹中的文件,或者我在发布的代码片段中做了什么,那也会有所帮助
谢谢大家! 使用数据库:
使用mysql等数据库存储所有音频信息和元数据。排序和重复检查将更容易实现
对音频文件进行分类:
根据类型将文件分类到单独的文件夹中。如果音频文件数量巨大,则在排序后,您一次只能加载一个页面,然后继续后续页面
在播放列表中使用智能指针:
使用std::shared_ptr从媒体文件夹加载到播放列表。这将进一步减少内存消耗。例如,如果在音频文件之间插入广告,则这两部分可能仍然具有相同的字段。您应该尝试查看模型视图控制器框架类,如
他们有proxymodels的概念,而不是基于内存、文件系统或基于sqlite的数据的模型,这些代理模型具有排序和过滤等功能
创建GUi也是自动的,因为您只需要将列表视图或树视图与代理模型连接起来
这些都是高度优化的模型,排序和过滤也非常高效,代码更少。也许你想对数据使用sqlite。因为多个艺术家可以共享曲目——建议使用std::vector
而不是std::vector
,我认为在这种情况下,sqlite将是比mysql更好的选择。
#pragma once
#include <vector>
#include "Track.h"
#include <string>
class Artist
{
public:
Artist (std::wstring artistName);
~Artist ();
std::wstring artistName;
std::vector<Track*> tracks;
};