libsaria: Remove libsaria
My new implementation puts everything under lib/ instead of treating the backend library as a different project. Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
parent
c65c8b06f2
commit
0281a7653d
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
import config
|
|
||||||
|
|
||||||
config.env.ParseConfig('pkg-config --cflags --libs gstreamer-0.10')
|
|
||||||
#config.env.ParseConfig('pkg-config --cflags --libs gstreamer-interfaces-0.10')
|
|
||||||
config.env.ParseConfig('pkg-config --cflags --libs taglib')
|
|
||||||
|
|
||||||
files = config.get_cpp_files()
|
|
||||||
Return('files')
|
|
|
@ -1,190 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <deck.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static GstElement *player = NULL;
|
|
||||||
static GstFormat fmt_time = GST_FORMAT_TIME;
|
|
||||||
static GstState cur_state = GST_STATE_READY;
|
|
||||||
|
|
||||||
static void notify_state_change(GstState state)
|
|
||||||
{
|
|
||||||
if (state == GST_STATE_PLAYING)
|
|
||||||
libsaria::notify(PLAYING, NULL);
|
|
||||||
else if (state == GST_STATE_PAUSED)
|
|
||||||
libsaria::notify(PAUSED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool change_state(GstState new_state)
|
|
||||||
{
|
|
||||||
GstStateChangeReturn ret;
|
|
||||||
ret = gst_element_set_state(GST_ELEMENT(player), new_state);
|
|
||||||
|
|
||||||
switch(ret) {
|
|
||||||
case GST_STATE_CHANGE_SUCCESS:
|
|
||||||
case GST_STATE_CHANGE_ASYNC:
|
|
||||||
cur_state = new_state;
|
|
||||||
notify_state_change(cur_state);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_file(GstElement *playbin, string file, GstState state)
|
|
||||||
{
|
|
||||||
gchar *escaped;
|
|
||||||
if (file == "" || !libsaria::exists(file))
|
|
||||||
return;
|
|
||||||
|
|
||||||
println("Loading file: " + file);
|
|
||||||
escaped = gst_filename_to_uri(file.c_str(), NULL);
|
|
||||||
|
|
||||||
/* Set pipeline to the requested state */
|
|
||||||
change_state(GST_STATE_READY);
|
|
||||||
g_object_set(G_OBJECT(playbin), "uri", escaped, NULL);
|
|
||||||
change_state(state);
|
|
||||||
|
|
||||||
g_free(escaped);
|
|
||||||
}
|
|
||||||
|
|
||||||
static string to_string(gint64 time)
|
|
||||||
{
|
|
||||||
stringstream stream;
|
|
||||||
int minutes, seconds;
|
|
||||||
|
|
||||||
if (time == 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
time = time / GST_SECOND;
|
|
||||||
minutes = time / 60;
|
|
||||||
seconds = time - (minutes * 60);
|
|
||||||
stream << minutes << ":";
|
|
||||||
if (seconds < 10)
|
|
||||||
stream << "0";
|
|
||||||
stream << seconds;
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parse_error(GstMessage *error)
|
|
||||||
{
|
|
||||||
GError *err;
|
|
||||||
gchar *debug;
|
|
||||||
|
|
||||||
gst_message_parse_error(error, &err, &debug);
|
|
||||||
g_print("Error: %s\n", err->message);
|
|
||||||
g_error_free(err);
|
|
||||||
g_free(debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean on_message(GstBus *bus, GstMessage *message, gpointer data)
|
|
||||||
{
|
|
||||||
switch (GST_MESSAGE_TYPE(message)) {
|
|
||||||
case GST_MESSAGE_ERROR:
|
|
||||||
parse_error(message);
|
|
||||||
case GST_MESSAGE_EOS:
|
|
||||||
libsaria::deck::next();
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void audio::play()
|
|
||||||
{
|
|
||||||
change_state(GST_STATE_PLAYING);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::pause()
|
|
||||||
{
|
|
||||||
change_state(GST_STATE_PAUSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::toggle_play()
|
|
||||||
{
|
|
||||||
if (cur_state == GST_STATE_PLAYING)
|
|
||||||
pause();
|
|
||||||
else
|
|
||||||
play();
|
|
||||||
}
|
|
||||||
|
|
||||||
GstState audio::get_state()
|
|
||||||
{
|
|
||||||
return cur_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::stop()
|
|
||||||
{
|
|
||||||
pause();
|
|
||||||
seek_to(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::load(string file, bool play)
|
|
||||||
{
|
|
||||||
GstState state = GST_STATE_PLAYING;
|
|
||||||
if (!play)
|
|
||||||
state = GST_STATE_PAUSED;
|
|
||||||
load_file(player, file, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Seek to this many seconds into the song */
|
|
||||||
void audio::seek_to(double pos)
|
|
||||||
{
|
|
||||||
gst_element_seek_simple(GST_ELEMENT(player),
|
|
||||||
GST_FORMAT_TIME,
|
|
||||||
GST_SEEK_FLAG_FLUSH,
|
|
||||||
pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
gint64 audio::duration()
|
|
||||||
{
|
|
||||||
gint64 duration;
|
|
||||||
if (!gst_element_query_duration(player, &fmt_time, &duration))
|
|
||||||
return 0;
|
|
||||||
if (duration < 0)
|
|
||||||
duration = 0;
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
gint64 audio::position()
|
|
||||||
{
|
|
||||||
gint64 position;
|
|
||||||
if (!gst_element_query_position(player, &fmt_time, &position))
|
|
||||||
return 0;
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
string audio::posstr()
|
|
||||||
{
|
|
||||||
return to_string(position());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool audio::played()
|
|
||||||
{
|
|
||||||
return position() > ((duration() * 3) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::init(int argc, char **argv)
|
|
||||||
{
|
|
||||||
static GstBus *bus;
|
|
||||||
println("Initializing libsaria audio");
|
|
||||||
gst_init(&argc, &argv);
|
|
||||||
|
|
||||||
player = gst_element_factory_make("playbin2", "player");
|
|
||||||
bus = gst_pipeline_get_bus(GST_PIPELINE(player));
|
|
||||||
|
|
||||||
gst_bus_add_watch(bus, on_message, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::quit()
|
|
||||||
{
|
|
||||||
gst_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <playlist.h>
|
|
||||||
#include <library.h>
|
|
||||||
#include <ban.h>
|
|
||||||
|
|
||||||
static libsaria::Playlist banned_plist(PL_STATIC | PL_NO_DRAIN | PL_RANDOM | PL_SORTED);
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
Playlist *ban::get_banned_plist()
|
|
||||||
{
|
|
||||||
return &banned_plist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ban::track_banned(Track *track)
|
|
||||||
{
|
|
||||||
/* Remove from library playlist */
|
|
||||||
library::get_playlist()->remove_track(track);
|
|
||||||
|
|
||||||
/* Add to banned list */
|
|
||||||
banned_plist.push_back(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ban::track_unbanned(Track *track)
|
|
||||||
{
|
|
||||||
/* Remove from banned list */
|
|
||||||
banned_plist.remove_track(track);
|
|
||||||
|
|
||||||
/* Add to library playlist */
|
|
||||||
library::get_playlist()->push_back(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <deck.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <library.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static AutoPauseType pause_type;
|
|
||||||
static unsigned short pause_count = 0;
|
|
||||||
|
|
||||||
static vector<libsaria::Playlist *> playlist_deck;
|
|
||||||
static libsaria::Playlist recent_playlist(PL_STATIC | PL_NO_DRAIN | PL_UNIQUE);
|
|
||||||
|
|
||||||
static libsaria::Playlist *get_active_playlist()
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++) {
|
|
||||||
if (!playlist_deck[i]->check_flag(PL_DISABLED))
|
|
||||||
return playlist_deck[i];
|
|
||||||
}
|
|
||||||
return libsaria::library::get_playlist();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool check_play()
|
|
||||||
{
|
|
||||||
switch(pause_type) {
|
|
||||||
case PS_AFTER_N:
|
|
||||||
if (pause_count == 0) {
|
|
||||||
libsaria::deck::set_pause_type(PS_NONE, 0);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
pause_count--;
|
|
||||||
libsaria::notify(PAUSE_COUNT, &pause_count);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_playlist(libsaria::Playlist *plist)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++) {
|
|
||||||
if (playlist_deck[i] == plist) {
|
|
||||||
playlist_deck.erase(playlist_deck.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void renumber_playlists()
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++)
|
|
||||||
playlist_deck[i]->renumber(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_playlist(ifstream &stream)
|
|
||||||
{
|
|
||||||
libsaria::Playlist *plist = new libsaria::Playlist(0);
|
|
||||||
playlist_deck.push_back(plist);
|
|
||||||
notify(PLAYLIST_NEW, plist);
|
|
||||||
plist->load(stream);
|
|
||||||
plist->renumber(playlist_deck.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void deck::garbage_collect()
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++) {
|
|
||||||
Playlist *plist = playlist_deck[i];
|
|
||||||
if (plist->get_size() == 0) {
|
|
||||||
plist->prepare_for_removal();
|
|
||||||
notify(PLAYLIST_DELETE, plist);
|
|
||||||
delete plist;
|
|
||||||
playlist_deck.erase(playlist_deck.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renumber_playlists();
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::next()
|
|
||||||
{
|
|
||||||
Playlist *plist = get_active_playlist();
|
|
||||||
Track *track = plist->next();
|
|
||||||
if (track)
|
|
||||||
track->load(check_play());
|
|
||||||
garbage_collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::prev()
|
|
||||||
{
|
|
||||||
Track *track = recent_playlist.next();
|
|
||||||
if (track)
|
|
||||||
track->load_unlisted(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist *deck::new_playlist(list<Track *> &tracks, unsigned int flags, bool front)
|
|
||||||
{
|
|
||||||
Playlist *plist;
|
|
||||||
|
|
||||||
if (playlist_deck.size() == MAX_PLAYLISTS)
|
|
||||||
return NULL;
|
|
||||||
plist = new Playlist(flags);
|
|
||||||
|
|
||||||
if (front)
|
|
||||||
playlist_deck.insert(playlist_deck.begin(), plist);
|
|
||||||
else
|
|
||||||
playlist_deck.push_back(plist);
|
|
||||||
notify(PLAYLIST_NEW, plist);
|
|
||||||
|
|
||||||
renumber_playlists();
|
|
||||||
plist->push_back(tracks);
|
|
||||||
return plist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::delete_playlist(Playlist *plist)
|
|
||||||
{
|
|
||||||
plist->prepare_for_removal();
|
|
||||||
notify(PLAYLIST_DELETE, plist);
|
|
||||||
remove_playlist(plist);
|
|
||||||
garbage_collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int deck::move_playlist(Playlist *plist, unsigned int index)
|
|
||||||
{
|
|
||||||
if (index >= playlist_deck.size())
|
|
||||||
index = playlist_deck.size() - 1;
|
|
||||||
|
|
||||||
remove_playlist(plist);
|
|
||||||
playlist_deck.insert(playlist_deck.begin() + index, plist);
|
|
||||||
renumber_playlists();
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::track_removed(Track *track)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++)
|
|
||||||
playlist_deck[i]->remove_track(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist *deck::get_recent_plist()
|
|
||||||
{
|
|
||||||
return &recent_playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::list_recent(Track *track)
|
|
||||||
{
|
|
||||||
recent_playlist.push_front(track);
|
|
||||||
recent_playlist.reset_iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist *deck::get_playlist(unsigned int n)
|
|
||||||
{
|
|
||||||
if (n >= playlist_deck.size())
|
|
||||||
return NULL;
|
|
||||||
return playlist_deck[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int deck::get_playlist_index(Playlist *plist)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < playlist_deck.size(); i++) {
|
|
||||||
if (playlist_deck[i] == plist)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int deck::size()
|
|
||||||
{
|
|
||||||
return playlist_deck.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::init()
|
|
||||||
{
|
|
||||||
app::mkdir("playlist");
|
|
||||||
app::read_numdir("playlist", read_playlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deck::set_pause_type(AutoPauseType type, unsigned int count)
|
|
||||||
{
|
|
||||||
pause_type = type;
|
|
||||||
pause_count = count;
|
|
||||||
notify(PAUSE_TYPE, &pause_type);
|
|
||||||
notify(PAUSE_COUNT, &count);
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoPauseType deck::get_pause_type()
|
|
||||||
{
|
|
||||||
return pause_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short deck::get_pause_count()
|
|
||||||
{
|
|
||||||
return pause_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* Namespace: Libsaria */
|
|
|
@ -1,209 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <format.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static map<string, set<string> > format_cache;
|
|
||||||
static map<string, set<string> > substr_cache;
|
|
||||||
static map<string, string> lc_cache;
|
|
||||||
static unsigned int format_hits = 0;
|
|
||||||
static unsigned int substr_hits = 0;
|
|
||||||
static unsigned int lc_hits = 0;
|
|
||||||
|
|
||||||
static const unsigned int TM_SECOND = 1;
|
|
||||||
static const unsigned int TM_MINUTE = 60;
|
|
||||||
static const unsigned int TM_HOUR = TM_MINUTE * 60;
|
|
||||||
static const unsigned int TM_DAY = TM_HOUR * 24;
|
|
||||||
|
|
||||||
void do_format(const string &text,
|
|
||||||
map<string, set<string> >::iterator &words,
|
|
||||||
map<string, string>::iterator &lc)
|
|
||||||
{
|
|
||||||
string word;
|
|
||||||
string lc_string;
|
|
||||||
set<string> word_set;
|
|
||||||
pair< map<string, set<string> >::iterator, bool > ret1;
|
|
||||||
pair< map<string, string>::iterator, bool > ret2;
|
|
||||||
char c, diff = 'a' - 'A';
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < text.size(); i++) {
|
|
||||||
c = text[i];
|
|
||||||
// Character already lower case
|
|
||||||
if ( (c >= 'a') && (c <= 'z') )
|
|
||||||
word += c;
|
|
||||||
// Convert uppercase to lowercase
|
|
||||||
else if ( (c >= 'A') && (c <= 'Z') )
|
|
||||||
word += (c + diff);
|
|
||||||
// Keep numbers
|
|
||||||
else if ( (c >= '0') && (c <= '9') )
|
|
||||||
word += c;
|
|
||||||
else {
|
|
||||||
// These characters indicate a new word
|
|
||||||
switch (c) {
|
|
||||||
case '-':
|
|
||||||
case '\\':
|
|
||||||
case '/':
|
|
||||||
case ',':
|
|
||||||
case ';':
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
case '_':
|
|
||||||
case '~':
|
|
||||||
case '+':
|
|
||||||
case '"':
|
|
||||||
case ' ':
|
|
||||||
if (word != "") {
|
|
||||||
word_set.insert(word);
|
|
||||||
if (lc_string == "")
|
|
||||||
lc_string = word;
|
|
||||||
else
|
|
||||||
lc_string += " " + word;
|
|
||||||
}
|
|
||||||
word = "";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (word != "") {
|
|
||||||
word_set.insert(word);
|
|
||||||
if (lc_string == "")
|
|
||||||
lc_string = word;
|
|
||||||
else
|
|
||||||
lc_string += " " + word;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret1 = format_cache.insert( pair<string, set<string> >(text, word_set) );
|
|
||||||
ret2 = lc_cache.insert( pair<string, string>(text, lc_string) );
|
|
||||||
words = ret1.first;
|
|
||||||
lc = ret2.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
void find_unique_words(const string &text,
|
|
||||||
map<string, set<string> >::iterator &words)
|
|
||||||
{
|
|
||||||
map<string, string>::iterator lc;
|
|
||||||
do_format(text, words, lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static set<string> *gen_substrs(const string &word)
|
|
||||||
{
|
|
||||||
string key;
|
|
||||||
set<string> substrs;
|
|
||||||
pair< map<string, set<string> >::iterator, bool > ret;
|
|
||||||
|
|
||||||
for (unsigned int i = 1; i <= word.size(); i++) {
|
|
||||||
key = word.substr(0, i);
|
|
||||||
substrs.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = substr_cache.insert( pair<string, set<string> >(word, substrs));
|
|
||||||
return &(ret.first->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
static set<string> *find_substrs(const string &word)
|
|
||||||
{
|
|
||||||
map<string, set<string> >::iterator it;
|
|
||||||
it = substr_cache.find(word);
|
|
||||||
if (it == substr_cache.end())
|
|
||||||
return gen_substrs(word);
|
|
||||||
else {
|
|
||||||
substr_hits++;
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void find_lowercase(const string &text,
|
|
||||||
map<string, string>::iterator &lc)
|
|
||||||
{
|
|
||||||
map<string, set<string> >::iterator words;
|
|
||||||
do_format(text, words, lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int add_to_stream(stringstream &stream, const unsigned int factor,
|
|
||||||
string field, unsigned int length, unsigned int total)
|
|
||||||
{
|
|
||||||
unsigned int res = length / factor;
|
|
||||||
if (res == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (total != 0)
|
|
||||||
stream << ", ";
|
|
||||||
stream << res << " " << field;
|
|
||||||
if (res > 1)
|
|
||||||
stream << "s";
|
|
||||||
|
|
||||||
return res * factor;;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
set<string> *format_text(const string &text)
|
|
||||||
{
|
|
||||||
map<string, set<string> >::iterator it;
|
|
||||||
it = format_cache.find(text);
|
|
||||||
|
|
||||||
/* Not found in cache... */
|
|
||||||
if (it == format_cache.end())
|
|
||||||
find_unique_words(text, it);
|
|
||||||
else
|
|
||||||
format_hits++;
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
void format_substrs(const string &text, set<string> &res)
|
|
||||||
{
|
|
||||||
set<string> *words, *substrs;
|
|
||||||
set<string>::iterator it;
|
|
||||||
|
|
||||||
words = format_text(text);
|
|
||||||
for (it = words->begin(); it != words->end(); it++) {
|
|
||||||
substrs = find_substrs(*it);
|
|
||||||
res.insert(substrs->begin(), substrs->end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string *lowercase(const string &text)
|
|
||||||
{
|
|
||||||
map<string, string>::iterator it;
|
|
||||||
it = lc_cache.find(text);
|
|
||||||
|
|
||||||
/* Not found in cache */
|
|
||||||
if (it == lc_cache.end())
|
|
||||||
find_lowercase(text, it);
|
|
||||||
else
|
|
||||||
lc_hits++;
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
string length_string(unsigned int len)
|
|
||||||
{
|
|
||||||
unsigned int tot;
|
|
||||||
stringstream stream;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
tot = add_to_stream(stream, TM_DAY, "day", len, 0);
|
|
||||||
tot += add_to_stream(stream, TM_HOUR, "hour", len - tot, tot);
|
|
||||||
tot += add_to_stream(stream, TM_MINUTE, "minute", len - tot, tot);
|
|
||||||
|
|
||||||
add_to_stream(stream, TM_SECOND, "second", len - tot, tot);
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_format_stats()
|
|
||||||
{
|
|
||||||
println("Format cache hits: %u size: %u", format_hits, format_cache.size());
|
|
||||||
println("Substring cache hits: %u size: %u", substr_hits, substr_cache.size());
|
|
||||||
println("Lowercase cache hits: %u size: %u", lc_hits, lc_cache.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* Namespace: libsaria */
|
|
211
libsaria/fs.cpp
211
libsaria/fs.cpp
|
@ -1,211 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <fs.h>
|
|
||||||
#include <idle.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static string appdir;
|
|
||||||
static mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
|
||||||
static bool pipe_opened = false;
|
|
||||||
|
|
||||||
static void make_dir(const string &path)
|
|
||||||
{
|
|
||||||
println("Making directory: " + path);
|
|
||||||
mkdir(path.c_str(), dirmode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_entry(string &dir, list<string> &file_list, struct dirent *dirp)
|
|
||||||
{
|
|
||||||
struct stat stat;
|
|
||||||
|
|
||||||
string name = dirp->d_name;
|
|
||||||
if (name == "." || name == "..")
|
|
||||||
return;
|
|
||||||
name = dir + "/" + name;
|
|
||||||
|
|
||||||
if (lstat(name.c_str(), &stat) == 0) {
|
|
||||||
if (S_ISDIR(stat.st_mode))
|
|
||||||
libsaria::list_dir(name, file_list);
|
|
||||||
else
|
|
||||||
file_list.push_back(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool compare_files(string &one, string &two)
|
|
||||||
{
|
|
||||||
unsigned int a = atoi(one.c_str());
|
|
||||||
unsigned int b = atoi(two.c_str());
|
|
||||||
return a < b;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ReadData
|
|
||||||
{
|
|
||||||
string filepath;
|
|
||||||
void (*func)(ifstream &);
|
|
||||||
};
|
|
||||||
|
|
||||||
static void read_cb(void *d)
|
|
||||||
{
|
|
||||||
ifstream stream;
|
|
||||||
struct ReadData *data = (struct ReadData *)d;
|
|
||||||
|
|
||||||
stream.open(data->filepath.c_str());
|
|
||||||
data->func(stream);
|
|
||||||
stream.close();
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WriteData
|
|
||||||
{
|
|
||||||
string filepath;
|
|
||||||
void (*func)(ofstream &, void *);
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void write_cb(void *d)
|
|
||||||
{
|
|
||||||
ofstream stream;
|
|
||||||
struct WriteData *data = (struct WriteData *)d;
|
|
||||||
|
|
||||||
stream.open(data->filepath.c_str());
|
|
||||||
data->func(stream, data->data);
|
|
||||||
stream.close();
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
bool exists(const string &filepath)
|
|
||||||
{
|
|
||||||
struct stat stat;
|
|
||||||
return lstat(filepath.c_str(), &stat) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_dir(string &dir, list<string> &file_list)
|
|
||||||
{
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *dirp;
|
|
||||||
|
|
||||||
dp = opendir(dir.c_str());
|
|
||||||
if (dp == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
do {
|
|
||||||
dirp = readdir(dp);
|
|
||||||
if (dirp)
|
|
||||||
handle_entry(dir, file_list, dirp);
|
|
||||||
} while (dirp != NULL);
|
|
||||||
closedir(dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::list_dir(const string &dir, list<string> &file_list)
|
|
||||||
{
|
|
||||||
list<string> files;
|
|
||||||
list<string>::iterator it;
|
|
||||||
|
|
||||||
string d = appdir + "/" + dir;
|
|
||||||
libsaria::list_dir(d, files);
|
|
||||||
|
|
||||||
/* Strip out appdir information */
|
|
||||||
for (it = files.begin(); it != files.end(); it++)
|
|
||||||
file_list.push_back( (*it).substr(d.size() + 1) );
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int app::read_numdir(const string &dir, void (*func)(ifstream &))
|
|
||||||
{
|
|
||||||
list<string> files;
|
|
||||||
list<string>::iterator it;
|
|
||||||
|
|
||||||
list_dir(dir, files);
|
|
||||||
if (files.size() == 0)
|
|
||||||
return 0;
|
|
||||||
files.sort(compare_files);
|
|
||||||
|
|
||||||
for (it = files.begin(); it != files.end(); it++) {
|
|
||||||
println("Reading path: " + dir + "/" + (*it));
|
|
||||||
read(dir + "/" + (*it), func);
|
|
||||||
}
|
|
||||||
|
|
||||||
return atoi(files.back().c_str()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::mkdir(const string &dir)
|
|
||||||
{
|
|
||||||
string d = appdir + "/" + dir;
|
|
||||||
make_dir(d.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::rm(const string &file)
|
|
||||||
{
|
|
||||||
string f = appdir + "/" + file;
|
|
||||||
remove(f.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::init()
|
|
||||||
{
|
|
||||||
string home = getenv("HOME");
|
|
||||||
appdir = home + "/.ocarina";
|
|
||||||
#ifdef DEBUG
|
|
||||||
appdir += "-debug";
|
|
||||||
#endif
|
|
||||||
make_dir(appdir.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::save(string file, void (*func)(ofstream &, void *), void *d)
|
|
||||||
{
|
|
||||||
struct WriteData *data = new struct WriteData;
|
|
||||||
data->filepath = appdir + "/" + file;
|
|
||||||
data->func = func;
|
|
||||||
data->data = d;
|
|
||||||
idle::schedule(write_cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::read(string file, void (*func)(ifstream &))
|
|
||||||
{
|
|
||||||
struct ReadData *data = new struct ReadData;
|
|
||||||
data->filepath = appdir + "/" + file;
|
|
||||||
data->func = func;
|
|
||||||
idle::schedule(read_cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::read_now(string file, void (*func)(ifstream &))
|
|
||||||
{
|
|
||||||
ifstream stream;
|
|
||||||
stream.open((appdir + "/" + file).c_str());
|
|
||||||
func(stream);
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::open_pipe()
|
|
||||||
{
|
|
||||||
string file = appdir + "/pipe";
|
|
||||||
if (!exists(file)) {
|
|
||||||
mkfifo(file.c_str(), 0644);
|
|
||||||
pipe_opened = true;
|
|
||||||
} else {
|
|
||||||
println("Pipe file: %s already exists, pipe not opened!",
|
|
||||||
file.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void app::close_pipe()
|
|
||||||
{
|
|
||||||
string file = appdir + "/pipe";
|
|
||||||
if (pipe_opened && exists(file))
|
|
||||||
rm("pipe");
|
|
||||||
}
|
|
||||||
|
|
||||||
string app::pipe_file()
|
|
||||||
{
|
|
||||||
if (pipe_opened)
|
|
||||||
return appdir + "/pipe";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* Namespace: libsaria */
|
|
|
@ -1,123 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <notify.h>
|
|
||||||
#include <idle.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class IdleTask
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void (*func)();
|
|
||||||
void (*func2)(void *);
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
IdleTask(void (*)());
|
|
||||||
IdleTask(void (*)(void *), void *);
|
|
||||||
~IdleTask();
|
|
||||||
void run();
|
|
||||||
bool should_cancel(void *);
|
|
||||||
};
|
|
||||||
|
|
||||||
static deque<IdleTask *> idle_queue;
|
|
||||||
static float queued = 0.0;
|
|
||||||
static float serviced = 0.0;
|
|
||||||
|
|
||||||
IdleTask::IdleTask(void (*f)())
|
|
||||||
{
|
|
||||||
func = f;
|
|
||||||
func2 = NULL;
|
|
||||||
data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdleTask::IdleTask(void (*f)(void *), void *d)
|
|
||||||
{
|
|
||||||
func = NULL;
|
|
||||||
func2 = f;
|
|
||||||
data = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdleTask::~IdleTask()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IdleTask::run()
|
|
||||||
{
|
|
||||||
if (func)
|
|
||||||
func();
|
|
||||||
else
|
|
||||||
func2(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IdleTask::should_cancel(void *d)
|
|
||||||
{
|
|
||||||
if (data && (data == d))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void queue_task(IdleTask *task)
|
|
||||||
{
|
|
||||||
idle_queue.push_back(task);
|
|
||||||
queued += 1.0;
|
|
||||||
libsaria::notify(IDLE_ADD, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
float idle::progress()
|
|
||||||
{
|
|
||||||
if (queued == 0)
|
|
||||||
return 1.0;
|
|
||||||
return (serviced / queued);
|
|
||||||
}
|
|
||||||
|
|
||||||
int idle::size()
|
|
||||||
{
|
|
||||||
return idle_queue.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void idle::schedule(void (*func)())
|
|
||||||
{
|
|
||||||
IdleTask *task = new IdleTask(func);
|
|
||||||
queue_task(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void idle::schedule(void (*func)(void *), void *data)
|
|
||||||
{
|
|
||||||
IdleTask *task = new IdleTask(func, data);
|
|
||||||
queue_task(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
int idle::run_task()
|
|
||||||
{
|
|
||||||
if (size() == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
idle_queue[0]->run();
|
|
||||||
delete idle_queue[0];
|
|
||||||
|
|
||||||
idle_queue.pop_front();
|
|
||||||
if (size() == 0) {
|
|
||||||
queued = 0.0;
|
|
||||||
serviced = 0.0;
|
|
||||||
} else
|
|
||||||
serviced += 1.0;
|
|
||||||
return size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void idle::cancel_all(void *data)
|
|
||||||
{
|
|
||||||
deque<IdleTask *>::iterator it;
|
|
||||||
for (it = idle_queue.begin(); it != idle_queue.end();) {
|
|
||||||
if ((*it)->should_cancel(data))
|
|
||||||
idle_queue.erase(it);
|
|
||||||
else
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
* Manages the libsaria library save file
|
|
||||||
*/
|
|
||||||
#include <library.h>
|
|
||||||
#include <notify.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <ban.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include "library.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#define LIBRARY_CURRENT_VERSION 3 /* 11/22/2012 */
|
|
||||||
static string libdir = "library";
|
|
||||||
|
|
||||||
static string id_to_filename(unsigned int id)
|
|
||||||
{
|
|
||||||
stringstream s;
|
|
||||||
s << id;
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_save_path(ofstream &stream, void *data)
|
|
||||||
{
|
|
||||||
libsaria::library::Path *path = (libsaria::library::Path *)data;
|
|
||||||
println("Saving library path: %d", path->id);
|
|
||||||
|
|
||||||
stream << LIBRARY_CURRENT_VERSION << "\n";
|
|
||||||
stream << path->path << "\n";
|
|
||||||
stream << path->id << " " << path->visible << " ";
|
|
||||||
stream << path->tracks.size() << "\n";
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < path->tracks.size(); i++)
|
|
||||||
path->tracks[i]->save(&stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void libsaria::library::save_path(libsaria::library::Path *path)
|
|
||||||
{
|
|
||||||
string filepath = libdir + "/" + id_to_filename(path->id);
|
|
||||||
libsaria::app::save(filepath, do_save_path, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_path(ifstream &stream)
|
|
||||||
{
|
|
||||||
string tmp;
|
|
||||||
stringstream s;
|
|
||||||
unsigned int size;
|
|
||||||
unsigned int version;
|
|
||||||
libsaria::Track *track;
|
|
||||||
struct libsaria::library::Path path, *path_ptr;
|
|
||||||
|
|
||||||
getline(stream, tmp);
|
|
||||||
s << tmp;
|
|
||||||
s >> version;
|
|
||||||
if (version > LIBRARY_CURRENT_VERSION)
|
|
||||||
return;
|
|
||||||
|
|
||||||
getline(stream, path.path);
|
|
||||||
|
|
||||||
getline(stream, tmp);
|
|
||||||
s.clear();
|
|
||||||
s.str(tmp);
|
|
||||||
|
|
||||||
s >> path.id >> path.visible;
|
|
||||||
if (version < 3) {
|
|
||||||
unsigned int next_track;
|
|
||||||
s >> next_track;
|
|
||||||
}
|
|
||||||
s >> size;
|
|
||||||
|
|
||||||
path_ptr = push_path(path);
|
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
|
||||||
track = new libsaria::Track(stream, path_ptr, version);
|
|
||||||
path_ptr->tracks.push_back(track);
|
|
||||||
track->id = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
libsaria::library::save_path(path_ptr);
|
|
||||||
libsaria::notify(PATH_UPDATED, path_ptr);
|
|
||||||
if (path.visible)
|
|
||||||
libsaria::library::show_path(path_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int schedule_load()
|
|
||||||
{
|
|
||||||
return libsaria::app::read_numdir(libdir, read_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_file(libsaria::library::Path *path)
|
|
||||||
{
|
|
||||||
string file = id_to_filename(path->id);
|
|
||||||
libsaria::app::rm(libdir + "/" + file);
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <playlist.h>
|
|
||||||
#include <library.h>
|
|
||||||
#include <notify.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <prefs.h>
|
|
||||||
#include <deck.h>
|
|
||||||
#include <idle.h>
|
|
||||||
#include <ban.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include "library.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static unsigned int next_id = 0;
|
|
||||||
static vector<struct libsaria::library::Path> path_list;
|
|
||||||
libsaria::Playlist lib_playlist(PL_STATIC | PL_NO_DRAIN | PL_SORTED);
|
|
||||||
|
|
||||||
libsaria::library::Path *push_path(libsaria::library::Path &path)
|
|
||||||
{
|
|
||||||
libsaria::library::Path *ptr;
|
|
||||||
|
|
||||||
path_list.push_back(path);
|
|
||||||
ptr = &path_list.back();
|
|
||||||
libsaria::notify(PATH_ADDED, ptr);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_track(libsaria::Track *track)
|
|
||||||
{
|
|
||||||
if (track->banned)
|
|
||||||
libsaria::ban::get_banned_plist()->remove_track(track);
|
|
||||||
else
|
|
||||||
lib_playlist.remove_track(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_path(libsaria::library::Path *path)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < path_list.size(); i++) {
|
|
||||||
if (&path_list[i] == path) {
|
|
||||||
libsaria::notify(PATH_DELETED, path);
|
|
||||||
path_list.erase(path_list.begin() + i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_current()
|
|
||||||
{
|
|
||||||
unsigned int l_id = libsaria::prefs::get("libsaria.current.library");
|
|
||||||
unsigned int t_id = libsaria::prefs::get("libsaria.current.track");
|
|
||||||
libsaria::Track *track = libsaria::library::lookup(l_id, t_id);
|
|
||||||
if (track)
|
|
||||||
track->load(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void library::add_path(string dir)
|
|
||||||
{
|
|
||||||
struct Path path, *path_ptr;
|
|
||||||
|
|
||||||
path.visible = true;
|
|
||||||
path.id = next_id++;
|
|
||||||
path.path = dir;
|
|
||||||
|
|
||||||
path_ptr = push_path(path);
|
|
||||||
update_path(path_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::delete_path(Path *path)
|
|
||||||
{
|
|
||||||
remove_file(path);
|
|
||||||
for (unsigned int i = 0; i < path->tracks.size(); i++) {
|
|
||||||
hide_track(path->tracks[i]);
|
|
||||||
libsaria::deck::track_removed(path->tracks[i]);
|
|
||||||
}
|
|
||||||
pop_path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::update_path(Path *path)
|
|
||||||
{
|
|
||||||
if (path)
|
|
||||||
do_update_path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::update_all()
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < path_list.size(); i++)
|
|
||||||
do_update_path(&path_list[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::hide_path(Path *path)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < path->tracks.size(); i++) {
|
|
||||||
hide_track(path->tracks[i]);
|
|
||||||
libsaria::deck::track_removed(path->tracks[i]);
|
|
||||||
}
|
|
||||||
path->visible = false;
|
|
||||||
save_path(path);
|
|
||||||
notify(PATH_UPDATED, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::show_path(Path *path)
|
|
||||||
{
|
|
||||||
list<Track *> ban, lib;
|
|
||||||
Track *track;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < path->tracks.size(); i++) {
|
|
||||||
track = path->tracks[i];
|
|
||||||
if (track->banned)
|
|
||||||
ban.push_back(track);
|
|
||||||
else
|
|
||||||
lib.push_back(track);
|
|
||||||
}
|
|
||||||
lib_playlist.push_back(lib);
|
|
||||||
ban::get_banned_plist()->push_back(ban);
|
|
||||||
|
|
||||||
path->visible = true;
|
|
||||||
save_path(path);
|
|
||||||
notify(PATH_UPDATED, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Track *library::lookup(unsigned int libid, unsigned int trackid)
|
|
||||||
{
|
|
||||||
if (libid >= path_list.size())
|
|
||||||
return NULL;
|
|
||||||
if (trackid >= path_list[libid].tracks.size())
|
|
||||||
return NULL;
|
|
||||||
return path_list[libid].tracks[trackid];
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::set_random(bool random)
|
|
||||||
{
|
|
||||||
prefs::set("libsaria.library.random", random);
|
|
||||||
lib_playlist.set_flag(PL_RANDOM, random);
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist *library::get_playlist()
|
|
||||||
{
|
|
||||||
return &lib_playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::init()
|
|
||||||
{
|
|
||||||
bool random = prefs::init("libsaria.library.random", true);
|
|
||||||
lib_playlist.set_flag(PL_RANDOM, random);
|
|
||||||
|
|
||||||
app::mkdir("library");
|
|
||||||
next_id = schedule_load();
|
|
||||||
idle::schedule(restore_current);
|
|
||||||
}
|
|
||||||
|
|
||||||
void library::quit()
|
|
||||||
{
|
|
||||||
struct libsaria::library::Path *path;
|
|
||||||
for (unsigned int i = 0; i < path_list.size(); i++) {
|
|
||||||
path = &path_list[i];
|
|
||||||
for (unsigned int j = 0; j < path->tracks.size(); j++)
|
|
||||||
delete path->tracks[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* namespace: libsaria */
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef LIBSARIA_LIBRARY_SOURCE_H
|
|
||||||
#define LIBSARIA_LIBRARY_SOURCE_H
|
|
||||||
|
|
||||||
#include <playlist.h>
|
|
||||||
#include <library.h>
|
|
||||||
|
|
||||||
extern libsaria::Playlist lib_playlist;
|
|
||||||
|
|
||||||
void do_update_path(struct libsaria::library::Path *);
|
|
||||||
libsaria::library::Path *push_path(libsaria::library::Path &);
|
|
||||||
unsigned int schedule_load();
|
|
||||||
void remove_file(libsaria::library::Path *);
|
|
||||||
|
|
||||||
#endif /* LIBSARIA_LIBRARY_SOURCE_H */
|
|
|
@ -1,127 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <library.h>
|
|
||||||
#include <notify.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <deck.h>
|
|
||||||
#include <idle.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include "library.h"
|
|
||||||
|
|
||||||
static unsigned int MAX_SCAN = 20;
|
|
||||||
|
|
||||||
static void validate_path(void *d)
|
|
||||||
{
|
|
||||||
struct libsaria::library::Path *path;
|
|
||||||
libsaria::Track *track;
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
path = (struct libsaria::library::Path *)d;
|
|
||||||
while (i < path->tracks.size()) {
|
|
||||||
track = path->tracks[i];
|
|
||||||
if (!libsaria::exists(track->filepath)) {
|
|
||||||
println("Reaping: " + track->filepath);
|
|
||||||
lib_playlist.remove_track(track);
|
|
||||||
path->tracks.erase(path->tracks.begin() + i);
|
|
||||||
} else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
libsaria::notify(PATH_UPDATED, path);
|
|
||||||
save_path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ScanData {
|
|
||||||
struct libsaria::library::Path *path;
|
|
||||||
list<string> files;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void setup_scan_data(struct ScanData *scan, list<string> &files)
|
|
||||||
{
|
|
||||||
list<string>::iterator it;
|
|
||||||
|
|
||||||
if (files.size() <= MAX_SCAN)
|
|
||||||
it = files.end();
|
|
||||||
else {
|
|
||||||
it = files.begin();
|
|
||||||
for (unsigned int i = 0; i < MAX_SCAN; i++)
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
scan->files.splice(scan->files.begin(), files, files.begin(), it);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool find_file(libsaria::library::Path *path, string &file)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < path->tracks.size(); i++) {
|
|
||||||
if (path->tracks[i]->filepath == file)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scan_path(void *data)
|
|
||||||
{
|
|
||||||
struct ScanData *scan = (struct ScanData *)data;
|
|
||||||
list<string>::iterator it;
|
|
||||||
libsaria::library::Path *path = scan->path;
|
|
||||||
libsaria::Track *track;
|
|
||||||
|
|
||||||
for (it = scan->files.begin(); it != scan->files.end(); it++) {
|
|
||||||
/*
|
|
||||||
* TODO: What I really should do for this check is build up
|
|
||||||
* a path component tree right before scanning, and then walk
|
|
||||||
* the tree to check if the path exists. It'll be much faster
|
|
||||||
* than having to walk the same list over and over...
|
|
||||||
*/
|
|
||||||
if (find_file(path, *it))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
try {
|
|
||||||
track = new libsaria::Track(*it, path);
|
|
||||||
path->tracks.push_back(track);
|
|
||||||
lib_playlist.push_back(track);
|
|
||||||
} catch (string message) {
|
|
||||||
println(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libsaria::notify(PATH_UPDATED, path);
|
|
||||||
delete scan;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_path(void *d)
|
|
||||||
{
|
|
||||||
struct libsaria::library::Path *path;
|
|
||||||
list<string> file_list;
|
|
||||||
unsigned int i;
|
|
||||||
struct ScanData *data;
|
|
||||||
|
|
||||||
path = (struct libsaria::library::Path *)d;
|
|
||||||
libsaria::list_dir(path->path, file_list);
|
|
||||||
println("Found: %d files to scan", file_list.size());
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (file_list.size() > 0) {
|
|
||||||
data = new ScanData;
|
|
||||||
data->path = path;
|
|
||||||
setup_scan_data(data, file_list);
|
|
||||||
libsaria::idle::schedule(scan_path, data);
|
|
||||||
if ((i++ % 50) == 0)
|
|
||||||
save_path(path);
|
|
||||||
}
|
|
||||||
save_path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_update_path(struct libsaria::library::Path *path)
|
|
||||||
{
|
|
||||||
println("Updating path: " + path->path);
|
|
||||||
|
|
||||||
if (!libsaria::exists(path->path)) {
|
|
||||||
libsaria::library::delete_path(path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
libsaria::idle::schedule(validate_path, path);
|
|
||||||
libsaria::idle::schedule(update_path, path);
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <libsaria.h>
|
|
||||||
#include <library.h>
|
|
||||||
#include <notify.h>
|
|
||||||
#include <format.h>
|
|
||||||
#include <prefs.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <deck.h>
|
|
||||||
#include <idle.h>
|
|
||||||
#include <fs.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static libsaria::Track outside_track;
|
|
||||||
static libsaria::initdata *app_data;
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void init(struct initdata *init)
|
|
||||||
{
|
|
||||||
app_data = init;
|
|
||||||
srand( time(NULL) );
|
|
||||||
println("Initializing libsaria");
|
|
||||||
|
|
||||||
app::init();
|
|
||||||
prefs::init();
|
|
||||||
|
|
||||||
audio::init(init->argc, init->argv);
|
|
||||||
libsaria::library::init();
|
|
||||||
libsaria::deck::init();
|
|
||||||
|
|
||||||
app::open_pipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quit()
|
|
||||||
{
|
|
||||||
println("Quitting libsaria");
|
|
||||||
app::close_pipe();
|
|
||||||
library::quit();
|
|
||||||
audio::quit();
|
|
||||||
print_format_stats();
|
|
||||||
}
|
|
||||||
|
|
||||||
void play_outside_song(string &filepath)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
outside_track = Track(filepath);
|
|
||||||
} catch (string message) {
|
|
||||||
println(message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
outside_track.load(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void notify(notify_t event, void *data)
|
|
||||||
{
|
|
||||||
if (app_data->on_notify)
|
|
||||||
app_data->on_notify(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,102 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <playlist.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static bool compare_tracks(libsaria::Track *one, libsaria::Track *two)
|
|
||||||
{
|
|
||||||
/* I want to compare tracks and not pointers */
|
|
||||||
return *one < *two;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void Playlist::add_track(Track *track, unsigned int ins_index)
|
|
||||||
{
|
|
||||||
track->add_playlist(this);
|
|
||||||
notify_ui(PLAYLIST_ADD, track, ins_index);
|
|
||||||
schedule_save();
|
|
||||||
if (plist.size() == 1)
|
|
||||||
cur = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::remove_index(unsigned int rm_index)
|
|
||||||
{
|
|
||||||
if (rm_index >= plist.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Track *track = plist[rm_index];
|
|
||||||
track->rm_playlist(this);
|
|
||||||
plist.erase(plist.begin() + rm_index);
|
|
||||||
if (cur > rm_index)
|
|
||||||
cur -= 1;
|
|
||||||
if (cur >= plist.size())
|
|
||||||
cur = 0;
|
|
||||||
notify_ui(PLAYLIST_RM, track, rm_index);
|
|
||||||
schedule_save();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::remove_track(Track *track)
|
|
||||||
{
|
|
||||||
remove_index(find_index(track));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::remove_indices(list<unsigned int> &indices)
|
|
||||||
{
|
|
||||||
list<unsigned int>::iterator it;
|
|
||||||
|
|
||||||
if (check_flag(PL_STATIC))
|
|
||||||
return;
|
|
||||||
indices.sort();
|
|
||||||
|
|
||||||
for (it = indices.begin(); it != indices.end(); it++)
|
|
||||||
remove_index(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::push_front(Track *track)
|
|
||||||
{
|
|
||||||
if (check_flag(PL_UNIQUE))
|
|
||||||
remove_track(track);
|
|
||||||
|
|
||||||
plist.insert(plist.begin(), track);
|
|
||||||
add_track(track, 0);
|
|
||||||
|
|
||||||
if (check_flag(PL_SORTED))
|
|
||||||
do_sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::push_back(Track *track)
|
|
||||||
{
|
|
||||||
if (check_flag(PL_UNIQUE))
|
|
||||||
remove_track(track);
|
|
||||||
|
|
||||||
plist.push_back(track);
|
|
||||||
add_track(track, plist.size());
|
|
||||||
|
|
||||||
if (check_flag(PL_SORTED))
|
|
||||||
do_sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::push_back(list<Track *> &tracks)
|
|
||||||
{
|
|
||||||
list<Track *>::iterator it;
|
|
||||||
for (it = tracks.begin(); it != tracks.end(); it++) {
|
|
||||||
plist.push_back(*it);
|
|
||||||
add_track(*it, plist.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_flag(PL_SORTED))
|
|
||||||
do_sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::do_sort()
|
|
||||||
{
|
|
||||||
sort(plist.begin(), plist.end(), compare_tracks);
|
|
||||||
notify_update_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* namespace: libsaria */
|
|
|
@ -1,120 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <playlist.h>
|
|
||||||
#include <library.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <deck.h>
|
|
||||||
#include <idle.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#define PLAYLIST_CURRENT_VERSION 3 // 9 / 14 / 2012
|
|
||||||
|
|
||||||
static string plistdir = "playlist";
|
|
||||||
|
|
||||||
static string number_to_filename(unsigned int id)
|
|
||||||
{
|
|
||||||
stringstream s;
|
|
||||||
s << id;
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_playlist(ofstream &stream, void *plist)
|
|
||||||
{
|
|
||||||
libsaria::Playlist *playlist = (libsaria::Playlist *)plist;
|
|
||||||
playlist->save(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void Playlist::load(ifstream &stream)
|
|
||||||
{
|
|
||||||
unsigned int version, type, size, libid, trackid;
|
|
||||||
bool disabled = false;
|
|
||||||
bool random = false;
|
|
||||||
bool sorted = false;
|
|
||||||
Track *track;
|
|
||||||
|
|
||||||
number = -1;
|
|
||||||
flags = 0;
|
|
||||||
cur = 0;
|
|
||||||
|
|
||||||
stream >> version;
|
|
||||||
if (version < 3)
|
|
||||||
stream >> type;
|
|
||||||
stream >> size >> disabled;
|
|
||||||
|
|
||||||
if (version >= 3)
|
|
||||||
stream >> random >> sorted;
|
|
||||||
else if (type == 0) { /* Old PLIST_SET type */
|
|
||||||
random = true;
|
|
||||||
sorted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
println("playlist size: %u disabled: %d random: %d sorted: %d",
|
|
||||||
size, disabled, random, sorted);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
|
||||||
stream >> libid >> trackid;
|
|
||||||
track = library::lookup(libid, trackid);
|
|
||||||
if (track)
|
|
||||||
push_back(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disabled)
|
|
||||||
flags |= PL_DISABLED;
|
|
||||||
if (random)
|
|
||||||
flags |= PL_RANDOM;
|
|
||||||
if (sorted) {
|
|
||||||
flags |= PL_SORTED;
|
|
||||||
do_sort();
|
|
||||||
}
|
|
||||||
notify(PLAYLIST_CHANGED, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::save(ofstream &stream)
|
|
||||||
{
|
|
||||||
stream << PLAYLIST_CURRENT_VERSION << "\n";
|
|
||||||
stream << plist.size() << " ";
|
|
||||||
stream << check_flag(PL_DISABLED) <<" ";
|
|
||||||
stream << check_flag(PL_RANDOM) << " ";
|
|
||||||
stream << check_flag(PL_SORTED) << "\n";
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < plist.size(); i++) {
|
|
||||||
stream << plist[i]->path->id << " ";
|
|
||||||
stream << plist[i]->id << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::schedule_save()
|
|
||||||
{
|
|
||||||
string filepath;
|
|
||||||
|
|
||||||
if (number < 0)
|
|
||||||
return;
|
|
||||||
else if (get_size() == 0) {
|
|
||||||
rm_file();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filepath = plistdir + "/" + number_to_filename(number);
|
|
||||||
app::save(filepath, save_playlist, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::rm_file()
|
|
||||||
{
|
|
||||||
string filepath;
|
|
||||||
|
|
||||||
if (number < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
idle::cancel_all(this);
|
|
||||||
filepath = plistdir + "/" + number_to_filename(number);
|
|
||||||
app::rm(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* Namespace: libsaria */
|
|
|
@ -1,140 +0,0 @@
|
||||||
// Copyright (c) 2012 Bryan Schumaker.
|
|
||||||
#include <track.h>
|
|
||||||
#include <library.h>
|
|
||||||
#include <playlist.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
Playlist::Playlist(unsigned int f)
|
|
||||||
{
|
|
||||||
number = -1;
|
|
||||||
flags = f;
|
|
||||||
cur = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist::~Playlist()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::set_flag(PlaylistFlags flag, bool enabled)
|
|
||||||
{
|
|
||||||
if (enabled) {
|
|
||||||
flags |= flag;
|
|
||||||
if (flag == PL_SORTED)
|
|
||||||
do_sort();
|
|
||||||
} else
|
|
||||||
flags &= ~flag;
|
|
||||||
schedule_save();
|
|
||||||
notify(PLAYLIST_CHANGED, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Playlist::check_flag(PlaylistFlags flag)
|
|
||||||
{
|
|
||||||
return (flags & flag) == flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::track_updated(Track *track)
|
|
||||||
{
|
|
||||||
notify_ui(PLAYLIST_UPDATE, track, find_index(track));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::prepare_for_removal()
|
|
||||||
{
|
|
||||||
vector<libsaria::Track *>::iterator it;
|
|
||||||
|
|
||||||
/* Remove playlist from tracks */
|
|
||||||
for (it = plist.begin(); it != plist.end(); it++)
|
|
||||||
(*it)->rm_playlist(this);
|
|
||||||
|
|
||||||
rm_file();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::renumber(int n)
|
|
||||||
{
|
|
||||||
if (number == n)
|
|
||||||
return;
|
|
||||||
if (n < number)
|
|
||||||
rm_file();
|
|
||||||
number = n;
|
|
||||||
schedule_save();
|
|
||||||
notify(PLAYLIST_RENUMBER, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Playlist::get_number()
|
|
||||||
{
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Playlist::get_size()
|
|
||||||
{
|
|
||||||
return plist.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Playlist::get_length()
|
|
||||||
{
|
|
||||||
unsigned int res = 0;
|
|
||||||
for (unsigned int i = 0; i < plist.size(); i++)
|
|
||||||
res += plist[i]->length;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::reset_iterator()
|
|
||||||
{
|
|
||||||
cur = 0;
|
|
||||||
notify_ui(PLAYLIST_GOTO, plist[cur], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Playlist::find_index(Track *track)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < plist.size(); i++) {
|
|
||||||
if (plist[i] == track)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return plist.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Track *Playlist::next()
|
|
||||||
{
|
|
||||||
Track *track;
|
|
||||||
unsigned int size = get_size();
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
return NULL;
|
|
||||||
else if (size == 1)
|
|
||||||
cur = 0;
|
|
||||||
else if (check_flag(PL_RANDOM))
|
|
||||||
cur += rand() % ((get_size() * 3) / 4);
|
|
||||||
else if (flags & PL_NO_DRAIN)
|
|
||||||
cur++;
|
|
||||||
|
|
||||||
if (cur >= size)
|
|
||||||
cur -= size;
|
|
||||||
|
|
||||||
track = plist[cur];
|
|
||||||
if (!(flags & PL_NO_DRAIN))
|
|
||||||
remove_index(cur);
|
|
||||||
|
|
||||||
if (get_size() != 0)
|
|
||||||
notify_ui(PLAYLIST_GOTO, track, cur);
|
|
||||||
return track;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::notify_ui(notify_t type, Track *track, unsigned int index)
|
|
||||||
{
|
|
||||||
struct PlaylistNotification data;
|
|
||||||
data.plist = this;
|
|
||||||
data.track = track;
|
|
||||||
data.index = index;
|
|
||||||
notify(type, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Playlist::notify_update_all()
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < plist.size(); i++)
|
|
||||||
notify_ui(PLAYLIST_UPDATE, plist[i], i);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <print.h>
|
|
||||||
#include <prefs.h>
|
|
||||||
#include <fs.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <fstream>
|
|
||||||
#include <stdlib.h>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static map<string, int> preferences;
|
|
||||||
|
|
||||||
static void save(ofstream &stream, void *data)
|
|
||||||
{
|
|
||||||
map<string, int>::iterator it;
|
|
||||||
println("Saving preferences!");
|
|
||||||
|
|
||||||
for (it = preferences.begin(); it != preferences.end(); it++) {
|
|
||||||
stream << it->first << endl;
|
|
||||||
stream << it->second << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load(ifstream &stream)
|
|
||||||
{
|
|
||||||
string key, value;
|
|
||||||
int val;
|
|
||||||
println("Loading preferences!");
|
|
||||||
|
|
||||||
while (stream.good()) {
|
|
||||||
getline(stream, key);
|
|
||||||
if (!stream.good())
|
|
||||||
break;
|
|
||||||
getline(stream, value);
|
|
||||||
if (!stream.good())
|
|
||||||
break;
|
|
||||||
val = atoi(value.c_str());
|
|
||||||
println(key + " = %d", val);
|
|
||||||
preferences[key] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_preference(const string &key, int p)
|
|
||||||
{
|
|
||||||
preferences[key] = p;
|
|
||||||
libsaria::app::save("prefs", save, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool key_exists(const string &key)
|
|
||||||
{
|
|
||||||
map<string, int>::iterator it;
|
|
||||||
it = preferences.find(key);
|
|
||||||
return it != preferences.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
void prefs::init()
|
|
||||||
{
|
|
||||||
libsaria::app::read_now("prefs", load);
|
|
||||||
}
|
|
||||||
|
|
||||||
int prefs::get(const string &key)
|
|
||||||
{
|
|
||||||
map<string, int>::iterator it;
|
|
||||||
it = preferences.find(key);
|
|
||||||
if (it == preferences.end())
|
|
||||||
return 0;
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void prefs::set(const string &key, int value)
|
|
||||||
{
|
|
||||||
if (get(key) != value)
|
|
||||||
set_preference(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int prefs::init(const string &key, int value)
|
|
||||||
{
|
|
||||||
if (!key_exists(key)) {
|
|
||||||
set_preference(key, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* Namespace: libsaria */
|
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdarg>
|
|
||||||
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
void print(string fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vprintf(fmt.c_str(), ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void println(string fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
fmt += "\n";
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vprintf(fmt.c_str(), ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* DEBUG */
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright (c) Bryan Schumaker 2012.
|
|
||||||
#include <libsaria.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <deck.h>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void libsaria::run_cmd(string &cmd)
|
|
||||||
{
|
|
||||||
if (cmd == "play")
|
|
||||||
libsaria::audio::play();
|
|
||||||
else if (cmd == "pause")
|
|
||||||
libsaria::audio::pause();
|
|
||||||
else if (cmd == "stop")
|
|
||||||
libsaria::audio::stop();
|
|
||||||
else if (cmd == "toggle")
|
|
||||||
libsaria::audio::toggle_play();
|
|
||||||
else if (cmd == "next")
|
|
||||||
libsaria::deck::next();
|
|
||||||
else if (cmd == "prev")
|
|
||||||
libsaria::deck::prev();
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <library.h>
|
|
||||||
#include <track.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
string Track::get_last_played()
|
|
||||||
{
|
|
||||||
stringstream s;
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
return "Never";
|
|
||||||
s << last_month << " / ";
|
|
||||||
s << last_day << " / ";
|
|
||||||
s << last_year;
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* Namespace: libsaria */
|
|
|
@ -1,47 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <library.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <print.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return positive value if s1 > s2
|
|
||||||
* Return negative value if s1 < s2
|
|
||||||
* Return 0 s1 == s2
|
|
||||||
*/
|
|
||||||
static inline int compare_strings(string *s1, string *s2)
|
|
||||||
{
|
|
||||||
/* List empty strings last */
|
|
||||||
if (*s1 == "")
|
|
||||||
return 1;
|
|
||||||
if (*s2 == "")
|
|
||||||
return -1;
|
|
||||||
return s1->compare(*s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Return true if this < cmp_track */
|
|
||||||
bool Track::operator<(Track &cmp_track)
|
|
||||||
{
|
|
||||||
int cmp;
|
|
||||||
|
|
||||||
/* Compare artists */
|
|
||||||
cmp = compare_strings(artist_lc, cmp_track.artist_lc);
|
|
||||||
if (cmp < 0)
|
|
||||||
return true;
|
|
||||||
else if (cmp > 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Compare albums */
|
|
||||||
cmp = compare_strings(album_lc, cmp_track.album_lc);
|
|
||||||
if (cmp < 0)
|
|
||||||
return true;
|
|
||||||
else if (cmp > 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Compare tracks */
|
|
||||||
return track < cmp_track.track;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <library.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <ban.h>
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void Track::set_banned(bool state)
|
|
||||||
{
|
|
||||||
banned = state;
|
|
||||||
libsaria::library::save_path(path);
|
|
||||||
|
|
||||||
if (state)
|
|
||||||
libsaria::ban::track_banned(this);
|
|
||||||
else
|
|
||||||
libsaria::ban::track_unbanned(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}; /* Namespace: libsaria */
|
|
|
@ -1,252 +0,0 @@
|
||||||
// Copyright (c) 2011 Bryan Schumaker.
|
|
||||||
#include <library.h>
|
|
||||||
#include <notify.h>
|
|
||||||
#include <format.h>
|
|
||||||
#include <track.h>
|
|
||||||
#include <audio.h>
|
|
||||||
#include <prefs.h>
|
|
||||||
#include <print.h>
|
|
||||||
#include <deck.h>
|
|
||||||
|
|
||||||
#include <taglib/tag.h>
|
|
||||||
#include <taglib/fileref.h>
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <algorithm>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static libsaria::Track *cur = NULL;
|
|
||||||
|
|
||||||
static void make_lenstr(unsigned int length, string &res)
|
|
||||||
{
|
|
||||||
int minutes;
|
|
||||||
int seconds;
|
|
||||||
stringstream stream;
|
|
||||||
|
|
||||||
/* Convert length into mm:ss format */
|
|
||||||
minutes = length / 60;
|
|
||||||
seconds = length - (minutes * 60);
|
|
||||||
stream << minutes << ":";
|
|
||||||
if (seconds < 10)
|
|
||||||
stream << "0";
|
|
||||||
stream << seconds;
|
|
||||||
res = stream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void escape_text(string &text)
|
|
||||||
{
|
|
||||||
replace(text.begin(), text.end(), '\n', ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace libsaria
|
|
||||||
{
|
|
||||||
|
|
||||||
void Track::read_tags()
|
|
||||||
{
|
|
||||||
TagLib::Tag *tag;
|
|
||||||
TagLib::AudioProperties *prop;
|
|
||||||
TagLib::FileRef ref(filepath.c_str());
|
|
||||||
|
|
||||||
if (ref.isNull())
|
|
||||||
throw "Error tagging file: " + filepath;
|
|
||||||
|
|
||||||
/* Extract tags */
|
|
||||||
tag = ref.tag();
|
|
||||||
title = tag->title().to8Bit(true);
|
|
||||||
artist = tag->artist().to8Bit(true);
|
|
||||||
album = tag->album().to8Bit(true);
|
|
||||||
comment = tag->comment().to8Bit(true);
|
|
||||||
genre = tag->genre().to8Bit(true);
|
|
||||||
year = tag->year();
|
|
||||||
track = tag->track();
|
|
||||||
|
|
||||||
/* Strip out newline characters */
|
|
||||||
escape_text(title);
|
|
||||||
escape_text(artist);
|
|
||||||
escape_text(album);
|
|
||||||
escape_text(comment);
|
|
||||||
escape_text(genre);
|
|
||||||
|
|
||||||
/* Extract audio properties */
|
|
||||||
prop = ref.audioProperties();
|
|
||||||
length = prop->length();
|
|
||||||
bitrate = prop->bitrate();
|
|
||||||
sample = prop->sampleRate();
|
|
||||||
channels = prop->channels();
|
|
||||||
}
|
|
||||||
|
|
||||||
Track::Track()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Track::Track(string file)
|
|
||||||
{
|
|
||||||
filepath = file;
|
|
||||||
banned = false;
|
|
||||||
read_tags();
|
|
||||||
}
|
|
||||||
|
|
||||||
Track::Track(string file, struct library::Path *lib_path)
|
|
||||||
{
|
|
||||||
filepath = file;
|
|
||||||
path = lib_path;
|
|
||||||
count = 0;
|
|
||||||
last_day = 0;
|
|
||||||
last_month = 0;
|
|
||||||
last_year = 0;
|
|
||||||
banned = false;
|
|
||||||
|
|
||||||
read_tags();
|
|
||||||
|
|
||||||
id = lib_path->tracks.size();
|
|
||||||
artist_lc = lowercase(artist);
|
|
||||||
album_lc = lowercase(album);
|
|
||||||
make_lenstr(length, lenstr);
|
|
||||||
find_substrs();
|
|
||||||
}
|
|
||||||
|
|
||||||
Track::Track(ifstream &in, struct library::Path *lib_path,
|
|
||||||
unsigned int version)
|
|
||||||
{
|
|
||||||
string tmp;
|
|
||||||
stringstream s;
|
|
||||||
|
|
||||||
path = lib_path;
|
|
||||||
|
|
||||||
getline(in, filepath);
|
|
||||||
getline(in, title);
|
|
||||||
getline(in, artist);
|
|
||||||
getline(in, album);
|
|
||||||
getline(in, comment);
|
|
||||||
getline(in, genre);
|
|
||||||
getline(in, lenstr);
|
|
||||||
getline(in, tmp);
|
|
||||||
|
|
||||||
s.clear();
|
|
||||||
s.str(tmp);
|
|
||||||
s >> id;
|
|
||||||
s >> year;
|
|
||||||
s >> track;
|
|
||||||
s >> count;
|
|
||||||
s >> last_day;
|
|
||||||
s >> last_month;
|
|
||||||
s >> last_year;
|
|
||||||
s >> length;
|
|
||||||
s >> bitrate;
|
|
||||||
s >> sample;
|
|
||||||
s >> channels;
|
|
||||||
|
|
||||||
if (version >= 2)
|
|
||||||
s >> banned;
|
|
||||||
else
|
|
||||||
banned = false;
|
|
||||||
|
|
||||||
artist_lc = lowercase(artist);
|
|
||||||
album_lc = lowercase(album);
|
|
||||||
find_substrs();
|
|
||||||
}
|
|
||||||
|
|
||||||
Track::~Track()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::mark_played()
|
|
||||||
{
|
|
||||||
time_t now = time(0);
|
|
||||||
tm *ltm = localtime(&now);
|
|
||||||
list<Playlist *>::iterator it;
|
|
||||||
|
|
||||||
if (path && audio::played()) {
|
|
||||||
count++;
|
|
||||||
last_day = ltm->tm_mday;
|
|
||||||
last_month = ltm->tm_mon + 1;
|
|
||||||
last_year = 1900 + ltm->tm_year;
|
|
||||||
|
|
||||||
library::save_path(path);
|
|
||||||
|
|
||||||
for (it = playlists.begin(); it != playlists.end(); it++)
|
|
||||||
(*it)->track_updated(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::load_unlisted(bool play)
|
|
||||||
{
|
|
||||||
if (cur)
|
|
||||||
cur->mark_played();
|
|
||||||
|
|
||||||
println("Loading: " + title + " by " + artist);
|
|
||||||
audio::load(filepath, play);
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
prefs::set("libsaria.current.library", path->id);
|
|
||||||
prefs::set("libsaria.current.track", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = this;
|
|
||||||
notify(TRACK_CHANGED, cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::load(bool play)
|
|
||||||
{
|
|
||||||
load_unlisted(play);
|
|
||||||
if (path)
|
|
||||||
deck::list_recent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Track *current_track()
|
|
||||||
{
|
|
||||||
return cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::save(ofstream *out)
|
|
||||||
{
|
|
||||||
*out << filepath << "\n";
|
|
||||||
*out << title << "\n";
|
|
||||||
*out << artist << "\n";
|
|
||||||
*out << album << "\n";
|
|
||||||
*out << comment << "\n";
|
|
||||||
*out << genre << "\n";
|
|
||||||
*out << lenstr << "\n";
|
|
||||||
*out << id << " ";
|
|
||||||
*out << year << " ";
|
|
||||||
*out << track << " ";
|
|
||||||
*out << count << " ";
|
|
||||||
*out << last_day << " ";
|
|
||||||
*out << last_month << " ";
|
|
||||||
*out << last_year << " ";
|
|
||||||
*out << length << " ";
|
|
||||||
*out << bitrate << " ";
|
|
||||||
*out << sample << " ";
|
|
||||||
*out << channels << " ";
|
|
||||||
*out << banned << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::add_playlist(Playlist *plist)
|
|
||||||
{
|
|
||||||
playlists.push_back(plist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::rm_playlist(Playlist *plist)
|
|
||||||
{
|
|
||||||
playlists.remove(plist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Track::find_substrs()
|
|
||||||
{
|
|
||||||
format_substrs(artist, substrs);
|
|
||||||
format_substrs(album, substrs);
|
|
||||||
format_substrs(title, substrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Track::is_visible(set<string> *search) {
|
|
||||||
set<string>::iterator it;
|
|
||||||
for (it = search->begin(); it != search->end(); it++) {
|
|
||||||
if (substrs.find(*it) == substrs.end())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* Namespace: libsaria */
|
|
Loading…
Reference in New Issue