文章目录

该类管理本地的音乐资料库并提供编辑本地音乐资料库的接口,定义于src/musikcore/library/LocalLibrary.h,继承了ILibrary、IMessageTarget类,并通过继承模板类std::enable_shared_from_this使得this指针成为shared_ptr指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class LocalLibrary :
public ILibrary,
public mymusic::core::runtime::IMessageTarget,
public std::enable_shared_from_this<LocalLibrary>
{
public:
using LocalQuery = mymusic::core::library::query::QueryBase;
using LocalQueryPtr = std::shared_ptr<LocalQuery>;
using MessageQueue = mymusic::core::runtime::IMessageQueue;
using IIndexer = mymusic::core::IIndexer;
/* 生成一个LocalLibrary对象,返回其智能指针 */
static ILibraryPtr Create(std::string name, int id, MessageQueue* messageQueue);
LocalLibrary(const LocalLibrary&) = delete;
/* LocalLibrary类析构函数:关闭该类(释放indexer成员,thread成员置空,清空queryQueue,exit置为true,通知所有等待在queueCondition上的线程,等待线程thread的结束,并回收它的资源);若messageQueue成员非空,将this从其中注销 */
virtual ~LocalLibrary();
/* ILibrary */
/* 将context加入queryQueue并通知所有等待在queryQueue上的线程 */
int Enqueue(QueryPtr query, Callback cb = Callback()) override;
/* 若timeoutMs=-1,则直接处理,无需加入队列;若timeoutMs=0,将context加入queryQueue并通知所有等待在queryQueue上的线程即可!若timeoutMs>0,则要么等待 timeoutMs退出,要么query提前被处理完(包括出错)然后退出 */
int EnqueueAndWait(QueryPtr query, size_t timeoutMs = kWaitIndefinite, Callback cb = Callback()) override;
/* 返回indexer成员 */
IIndexer *Indexer() override;
/* 返回id成员的值 */
int Id() override;
/* 返回name成员的值 */
const std::string& Name() override;
/* 设置消息队列messageQueue成员 */
void SetMessageQueue(mymusic::core::runtime::IMessageQueue& queue) override;
/* 返回messageQueue成员 */
MessageQueue& GetMessageQueue() override { return *messageQueue; }
/* 返回sResourceLocator */
IResourceLocator& GetResourceLocator() override;
/* 判断indexer成员是否设置了音乐资料库的路径 */
bool IsConfigured() override;
ConnectionState GetConnectionState() const override { return ConnectionState::Connected; }
Type GetType() const override { return Type::Local; }
/* 关闭该类(释放indexer成员,thread成员置空,清空queryQueue,exit置为true) */
void Close() override;
/* IMessageTarget */
/* 处理消息队列上的消息message */
void ProcessMessage(mymusic::core::runtime::IMessage &message) override;

/* implementation specific */
db::Connection& GetConnection() { return this->db; }
/* 获取资料库所在目录 */
std::string GetLibraryDirectory();
/* 获取数据库文件名 */
std::string GetDatabaseFilename();
/* 创建数据库 */
static void CreateDatabase(db::Connection &db);
/* indexes */
static void DropIndexes(db::Connection &db);
/* 创建数据库索引 */
static void CreateIndexes(db::Connection &db);
/* 删除播放记录 */
static void InvalidateTrackMetadata(db::Connection &db);
private:
class QueryCompletedMessage;

struct QueryContext {
LocalQueryPtr query;
/* 回调函数 */
Callback callback;
};

using QueryContextPtr = std::shared_ptr<QueryContext>;
/* 未使用... */
using QueryList = std::list<QueryContextPtr>;
/* LocalLibrary类构造函数:若messageQueue成员非空,在messageQueue上注册它本身;其identifier设置为id的字符串形式;与数据库文件*db建立连接 创建thread成员,运行的函数为ThreadProc */
LocalLibrary(std::string name, int id, MessageQueue* messageQueue); /* ctor */
/* 运行查询语句,查询完成后,若messageQueue成员非空,将查询完成的消息投递到messageQueue中;否则,通过sigslot消息传递机制来传递查询完成消息 */
void RunQuery(QueryContextPtr context, bool notify = true);
/* 主线程要运行的函数 */
void ThreadProc();
/* 获取queryQueue的第一个context(如果非空的话) */
QueryContextPtr GetNextQuery();
/* 查询队列 */
QueryList queryQueue;
/* 消息队列 */
mymusic::core::runtime::IMessageQueue* messageQueue;
/* 标识符 */
std::string identifier;
int id;
/* 音乐资料库名 */
std::string name;
/* 线程对象 */
std::thread* thread;
/* 条件变量,与mutex的锁配合使用 */
std::condition_variable_any queueCondition;
/* 互斥量 */
std::recursive_mutex mutex;
/* 标志是否退出 */
std::atomic<bool> exit;
/* 数据库的客户端 */
core::IIndexer *indexer;
/* 数据库连接 */
core::db::Connection db;
};