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:
Anna Schumaker 2013-12-25 14:40:12 -05:00 committed by Anna Schumaker
parent c65c8b06f2
commit 0281a7653d
22 changed files with 0 additions and 2289 deletions

View File

@ -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')

View File

@ -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();
}
};

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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++;
}
}
};

View File

@ -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);
}

View 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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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();
}

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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 */