Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 创建分类音乐库的有效方法_C++_Qt_Sorting_Vector_Set - Fatal编程技术网

C++ 创建分类音乐库的有效方法

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_

我正在尝试用qt/c++创建一个自己的音乐播放器/库。 我已经做的是扫描一个文件夹中的音乐文件,用taglib读取音乐文件的标签,从文件中创建一个
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;
};