libsaria: Add filtering to the new index
Otherwise it's useless. I search all three indexes and use the union of those results to determine what is visible.
This commit is contained in:
parent
9c749e4ade
commit
83488dfa06
|
@ -10,6 +10,10 @@ namespace libsaria
|
|||
{
|
||||
|
||||
void add_track(libsaria::Track &);
|
||||
void filter(string &);
|
||||
bool is_visible(sid_t &);
|
||||
bool is_filtered();
|
||||
unsigned int size();
|
||||
void print_stats();
|
||||
|
||||
}; /* Namespace: index */
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
#include <libsaria/index.h>
|
||||
#include <libsaria/format.h>
|
||||
#include <libsaria/callback.h>
|
||||
#include "index.h"
|
||||
|
||||
static set<sid_t> results;
|
||||
static bool filtered = false;
|
||||
|
||||
/*
|
||||
* Thanks to: http://stackoverflow.com/questions/1773526/in-place-c-set-intersection
|
||||
* for the set intersection algorithm!
|
||||
*/
|
||||
static void inplace_intersect(set<sid_t> *ids)
|
||||
{
|
||||
set<sid_t>::iterator it1 = results.begin();
|
||||
set<sid_t>::iterator it2 = ids->begin();
|
||||
|
||||
while ( (it1 != results.end()) && (it2 != ids->end()) ) {
|
||||
if (*it1 < *it2)
|
||||
results.erase(it1++);
|
||||
else if (*it2 < *it1)
|
||||
it2++;
|
||||
else { /* *it1 == *it2 */
|
||||
it1++;
|
||||
it2++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove everything in results that wasn't in inodes */
|
||||
results.erase(it1, results.end());
|
||||
|
||||
}
|
||||
|
||||
static inline void search_index(string &term,
|
||||
map<string, set<sid_t> > *index,
|
||||
set<ino_t> *found)
|
||||
{
|
||||
map<string, set<sid_t> >::iterator it;
|
||||
it = index->find(term);
|
||||
if (it != index->end())
|
||||
found->insert(it->second.begin(), it->second.end());
|
||||
}
|
||||
|
||||
static inline void search_indexes(string &term, set<ino_t> *found)
|
||||
{
|
||||
search_index(term, &artist_index, found);
|
||||
search_index(term, &album_index, found);
|
||||
search_index(term, &title_index, found);
|
||||
}
|
||||
|
||||
static void do_filter(list<string> *terms)
|
||||
{
|
||||
set<ino_t> found;
|
||||
list<string>::iterator it;
|
||||
|
||||
for (it = terms->begin(); it != terms->end(); it++) {
|
||||
found.clear();
|
||||
search_indexes(*it, &found);
|
||||
/*
|
||||
* Key not found means we don't need to filter anymore
|
||||
* just clear the results set and return.
|
||||
*/
|
||||
if (found.size() == 0) {
|
||||
results.clear();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* This is the first result, so the result set is empty.
|
||||
* Taking an intersection will always give us an empty set.
|
||||
*/
|
||||
if (it == terms->begin())
|
||||
results = found;
|
||||
else
|
||||
inplace_intersect(&found);
|
||||
}
|
||||
}
|
||||
|
||||
namespace libsaria
|
||||
{
|
||||
|
||||
void index::filter(string &search)
|
||||
{
|
||||
list<string> *terms = format_text(search);
|
||||
results.clear();
|
||||
|
||||
if (terms->size() == 0)
|
||||
filtered = false;
|
||||
else {
|
||||
do_filter(terms);
|
||||
filtered = true;
|
||||
}
|
||||
trigger_callback(REFILTER);
|
||||
}
|
||||
|
||||
bool index::is_visible(sid_t &songid)
|
||||
{
|
||||
set<sid_t>::iterator it;
|
||||
|
||||
if (filtered == false)
|
||||
return true;
|
||||
it = results.find(songid);
|
||||
return it != results.end();
|
||||
}
|
||||
|
||||
bool index::is_filtered()
|
||||
{
|
||||
return filtered;
|
||||
}
|
||||
|
||||
unsigned int index::size()
|
||||
{
|
||||
return results.size();
|
||||
}
|
||||
};
|
|
@ -2,6 +2,7 @@
|
|||
#include <libsaria/track.h>
|
||||
#include <libsaria/index.h>
|
||||
#include <libsaria/format.h>
|
||||
#include "index.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef LIBSARIA_INDEX_INTERNAL_H
|
||||
#define LIBSARIA_INDEX_INTERNAL_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
extern map<string, set<sid_t> > artist_index;
|
||||
extern map<string, set<sid_t> > album_index;
|
||||
extern map<string, set<sid_t> > title_index;
|
||||
|
||||
#endif /* LIBSARIA_INDEX_INTERNAL_H */
|
|
@ -6,6 +6,7 @@ using namespace std;
|
|||
|
||||
#include <libsaria/audio.h>
|
||||
#include <libsaria/prefs.h>
|
||||
#include <libsaria/index.h>
|
||||
#include <libsaria/print.h>
|
||||
#include "library.h"
|
||||
|
||||
|
@ -91,7 +92,7 @@ static void print_cur_track()
|
|||
static void random_next()
|
||||
{
|
||||
cur_track = play_list.begin();
|
||||
if (libsaria::library::is_filtered()) {
|
||||
if (libsaria::index::is_filtered()) {
|
||||
println("Picking random track from index");
|
||||
sid_t inode = libsaria::library::index_rand();
|
||||
libsaria::library::play_id(inode);
|
||||
|
@ -112,7 +113,7 @@ static void sequential_next()
|
|||
if (cur_track == play_list.end())
|
||||
cur_track = play_list.begin();
|
||||
inode = (*cur_track)->get_songid();
|
||||
} while (!libsaria::library::is_visible(inode));
|
||||
} while (!libsaria::index::is_visible(inode));
|
||||
}
|
||||
|
||||
static void pick_next()
|
||||
|
@ -197,8 +198,8 @@ namespace libsaria
|
|||
|
||||
unsigned int library::size()
|
||||
{
|
||||
if (is_filtered() == true)
|
||||
return filter_size();
|
||||
if (index::is_filtered() == true)
|
||||
return index::size();
|
||||
return play_list.size();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue