253 lines
4.6 KiB
C++
253 lines
4.6 KiB
C++
// 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 */
|