-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathload.cc
106 lines (86 loc) · 2.93 KB
/
load.cc
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
99
100
101
102
103
104
105
106
#include "load.h"
#include <iostream>
#include <unordered_map>
#include <vector>
#include <absl/hash/hash.h>
#include <absl/strings/str_format.h>
namespace ashuffle {
namespace {
// A Group is a vector of field values, present or not.
typedef std::vector<std::optional<std::string>> Group;
// A GroupMap is a mapping from Groups to song URI vectors of the URIs in the
// given group.
typedef std::unordered_map<Group, std::vector<std::string>, absl::Hash<Group>>
GroupMap;
} // namespace
/* build the list of songs to shuffle from using MPD */
void MPDLoader::Load(ShuffleChain *songs) {
GroupMap groups;
mpd::MPD::MetadataOption metadata = mpd::MPD::MetadataOption::kInclude;
if (rules_.empty() && group_by_.empty()) {
// If we don't need to process any rules, or group tracks, then we
// can omit metadata from the query. This is an optimization,
// mainly to avoid
// https://github.com/MusicPlayerDaemon/libmpdclient/issues/69
metadata = mpd::MPD::MetadataOption::kOmit;
}
auto reader_or = mpd_->ListAll(metadata);
if (!reader_or.ok()) {
Die("Failed to get reader: %s", reader_or.status().ToString());
}
std::unique_ptr<mpd::SongReader> reader = std::move(*reader_or);
while (!reader->Done()) {
std::unique_ptr<mpd::Song> song = *reader->Next();
if (!Verify(*song)) {
continue;
}
if (group_by_.empty()) {
songs->Add(song->URI());
continue;
}
Group group;
for (auto &field : group_by_) {
group.emplace_back(song->Tag(field));
}
groups[group].push_back(song->URI());
}
if (group_by_.empty()) {
return;
}
for (auto &&[_, group] : groups) {
songs->Add(group);
}
}
bool MPDLoader::Verify(const mpd::Song &song) {
for (const Rule &rule : rules_) {
if (!rule.Accepts(song)) {
return false;
}
}
return true;
}
FileMPDLoader::FileMPDLoader(mpd::MPD *mpd, const std::vector<Rule> &ruleset,
const std::vector<enum mpd_tag_type> &group_by,
std::istream *file)
: MPDLoader(mpd, ruleset, group_by), file_(file) {
for (std::string uri; std::getline(*file_, uri);) {
valid_uris_.emplace_back(uri);
}
std::sort(valid_uris_.begin(), valid_uris_.end());
}
bool FileMPDLoader::Verify(const mpd::Song &song) {
if (!std::binary_search(valid_uris_.begin(), valid_uris_.end(),
song.URI())) {
// If the URI for this song is not in the list of valid_uris_, then
// it shouldn't be loaded by this loader.
return false;
}
// Otherwise, just check against the normal rules.
return MPDLoader::Verify(song);
}
void FileLoader::Load(ShuffleChain *songs) {
for (std::string uri; std::getline(*file_, uri);) {
songs->Add(uri);
}
}
} // namespace ashuffle