Add a skipcount field to the database, and read the last played time into Song objects. (still not used in the GUI yet).

This commit is contained in:
David Sansome 2010-10-17 17:50:20 +00:00
parent dd4afe9b06
commit 42e4c4a8db
7 changed files with 57 additions and 8 deletions

View File

@ -278,5 +278,6 @@
<file>icons/22x22/rating.png</file> <file>icons/22x22/rating.png</file>
<file>icons/32x32/rating.png</file> <file>icons/32x32/rating.png</file>
<file>icons/48x48/rating.png</file> <file>icons/48x48/rating.png</file>
<file>schema/schema-18.sql</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -45,7 +45,9 @@ CREATE TABLE device_%deviceid_songs (
rating INTEGER, rating INTEGER,
forced_compilation_on INTEGER NOT NULL DEFAULT 0, forced_compilation_on INTEGER NOT NULL DEFAULT 0,
forced_compilation_off INTEGER NOT NULL DEFAULT 0, forced_compilation_off INTEGER NOT NULL DEFAULT 0,
effective_compilation NOT NULL DEFAULT 0 effective_compilation NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0
); );
CREATE INDEX idx_device_%deviceid_songs_album ON device_%deviceid_songs (album); CREATE INDEX idx_device_%deviceid_songs_album ON device_%deviceid_songs (album);

View File

@ -0,0 +1,4 @@
ALTER TABLE %allsongstables ADD COLUMN skipcount INTEGER NOT NULL DEFAULT 0;
UPDATE schema_version SET version=18;

View File

@ -29,7 +29,8 @@
#include <QVariant> #include <QVariant>
const char* Database::kDatabaseFilename = "clementine.db"; const char* Database::kDatabaseFilename = "clementine.db";
const int Database::kSchemaVersion = 17; const int Database::kSchemaVersion = 18;
const char* Database::kMagicAllSongsTables = "%allsongstables";
int Database::sNextConnectionId = 1; int Database::sNextConnectionId = 1;
QMutex Database::sNextConnectionIdMutex; QMutex Database::sNextConnectionIdMutex;
@ -447,12 +448,35 @@ void Database::ExecCommands(const QString &schema, QSqlDatabase &db) {
// Run each command // Run each command
QStringList commands(schema.split(";\n\n")); QStringList commands(schema.split(";\n\n"));
foreach (const QString& command, commands) { foreach (const QString& command, commands) {
QSqlQuery query(db.exec(command)); // There are now lots of "songs" tables that need to have the same schema:
if (CheckErrors(query.lastError())) // songs, magnatune_songs, and device_*_songs. We allow a magic value
qFatal("Unable to update music library database"); // in the schema files to update all songs tables at once.
if (command.contains(kMagicAllSongsTables)) {
foreach (const QString& table, SongsTables(db)) {
qDebug() << "Updating" << table << "for" << kMagicAllSongsTables;
QString new_command(command);
new_command.replace(kMagicAllSongsTables, table);
QSqlQuery query(db.exec(new_command));
if (CheckErrors(query.lastError()))
qFatal("Unable to update music library database");
}
} else {
QSqlQuery query(db.exec(command));
if (CheckErrors(query.lastError()))
qFatal("Unable to update music library database");
}
} }
} }
QStringList Database::SongsTables(QSqlDatabase& db) const {
QStringList ret;
foreach (const QString& table, db.tables()) {
if (table == "songs" || table.endsWith("_songs"))
ret << table;
}
return ret;
}
bool Database::CheckErrors(const QSqlError& error) { bool Database::CheckErrors(const QSqlError& error) {
if (error.isValid()) { if (error.isValid()) {
qDebug() << error; qDebug() << error;

View File

@ -43,6 +43,7 @@ class Database : public QObject {
static const int kSchemaVersion; static const int kSchemaVersion;
static const char* kDatabaseFilename; static const char* kDatabaseFilename;
static const char* kMagicAllSongsTables;
void Stop() {} void Stop() {}
@ -58,6 +59,7 @@ class Database : public QObject {
private: private:
void UpdateDatabaseSchema(int version, QSqlDatabase& db); void UpdateDatabaseSchema(int version, QSqlDatabase& db);
QStringList SongsTables(QSqlDatabase& db) const;
QString directory_; QString directory_;
QMutex connect_mutex_; QMutex connect_mutex_;

View File

@ -89,7 +89,7 @@ const QStringList Song::kColumns = QStringList()
<< "mtime" << "ctime" << "filesize" << "sampler" << "art_automatic" << "mtime" << "ctime" << "filesize" << "sampler" << "art_automatic"
<< "art_manual" << "filetype" << "playcount" << "lastplayed" << "rating" << "art_manual" << "filetype" << "playcount" << "lastplayed" << "rating"
<< "forced_compilation_on" << "forced_compilation_off" << "forced_compilation_on" << "forced_compilation_off"
<< "effective_compilation"; << "effective_compilation" << "skipcount";
const QString Song::kColumnSpec = Song::kColumns.join(", "); const QString Song::kColumnSpec = Song::kColumns.join(", ");
const QString Song::kBindSpec = Prepend(":", Song::kColumns).join(", "); const QString Song::kBindSpec = Prepend(":", Song::kColumns).join(", ");
@ -151,6 +151,8 @@ Song::Private::Private()
forced_compilation_off_(false), forced_compilation_off_(false),
rating_(-1.0), rating_(-1.0),
playcount_(0), playcount_(0),
skipcount_(0),
lastplayed_(-1),
length_(-1), length_(-1),
bitrate_(-1), bitrate_(-1),
samplerate_(-1), samplerate_(-1),
@ -459,7 +461,7 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
d->filetype_ = FileType(q.value(col + 24).toInt()); d->filetype_ = FileType(q.value(col + 24).toInt());
d->playcount_ = q.value(col + 25).isNull() ? 0 : q.value(col + 25).toInt(); d->playcount_ = q.value(col + 25).isNull() ? 0 : q.value(col + 25).toInt();
// lastplayed = 26 d->lastplayed_ = toint(col + 26);
d->rating_ = tofloat(col + 27); d->rating_ = tofloat(col + 27);
d->forced_compilation_on_ = q.value(col + 28).toBool(); d->forced_compilation_on_ = q.value(col + 28).toBool();
@ -467,6 +469,8 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
// effective_compilation = 30 // effective_compilation = 30
d->skipcount_ = q.value(col + 31).isNull() ? 0 : q.value(col + 31).toInt();
#undef tostr #undef tostr
#undef toint #undef toint
#undef tofloat #undef tofloat
@ -508,6 +512,8 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->filetype_ = track->type2 ? Type_Mpeg : Type_Mp4; d->filetype_ = track->type2 ? Type_Mpeg : Type_Mp4;
d->rating_ = float(track->rating) / 100; // 100 = 20 * 5 stars d->rating_ = float(track->rating) / 100; // 100 = 20 * 5 stars
d->playcount_ = track->playcount; d->playcount_ = track->playcount;
d->skipcount_ = track->skipcount;
d->lastplayed_ = track->time_played;
d->filename_ = QString::fromLocal8Bit(track->ipod_path); d->filename_ = QString::fromLocal8Bit(track->ipod_path);
d->filename_.replace(':', '/'); d->filename_.replace(':', '/');
@ -538,6 +544,8 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
track->mediatype = 1; // Audio track->mediatype = 1; // Audio
track->rating = d->rating_ * 100; // 100 = 20 * 5 stars track->rating = d->rating_ * 100; // 100 = 20 * 5 stars
track->playcount = d->playcount_; track->playcount = d->playcount_;
track->skipcount = d->skipcount_;
track->time_played = d->lastplayed_;
} }
#endif #endif
@ -905,7 +913,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
query->bindValue(":filetype", d->filetype_); query->bindValue(":filetype", d->filetype_);
query->bindValue(":playcount", d->playcount_); query->bindValue(":playcount", d->playcount_);
query->bindValue(":lastplayed", -1); // TODO query->bindValue(":lastplayed", intval(d->lastplayed_));
query->bindValue(":rating", intval(d->rating_)); query->bindValue(":rating", intval(d->rating_));
query->bindValue(":forced_compilation_on", d->forced_compilation_on_ ? 1 : 0); query->bindValue(":forced_compilation_on", d->forced_compilation_on_ ? 1 : 0);
@ -913,6 +921,8 @@ void Song::BindToQuery(QSqlQuery *query) const {
query->bindValue(":effective_compilation", is_compilation() ? 1 : 0); query->bindValue(":effective_compilation", is_compilation() ? 1 : 0);
query->bindValue(":skipcount", d->skipcount_);
#undef intval #undef intval
#undef notnullintval #undef notnullintval
} }

View File

@ -159,6 +159,8 @@ class Song {
} }
float rating() const { return d->rating_; } float rating() const { return d->rating_; }
int playcount() const { return d->playcount_; } int playcount() const { return d->playcount_; }
int skipcount() const { return d->skipcount_; }
int lastplayed() const { return d->lastplayed_; }
int length() const { return d->length_; } int length() const { return d->length_; }
int bitrate() const { return d->bitrate_; } int bitrate() const { return d->bitrate_; }
@ -217,6 +219,8 @@ class Song {
void set_forced_compilation_off(bool v) { d->forced_compilation_off_ = v; } void set_forced_compilation_off(bool v) { d->forced_compilation_off_ = v; }
void set_rating(float v) { d->rating_ = v; } void set_rating(float v) { d->rating_ = v; }
void set_playcount(int v) { d->playcount_ = v; } void set_playcount(int v) { d->playcount_ = v; }
void set_skipcount(int v) { d->skipcount_ = v; }
void set_lastplayed(int v) { d->lastplayed_ = v; }
// Setters that should only be used by tests // Setters that should only be used by tests
void set_filename(const QString& v) { d->filename_ = v; } void set_filename(const QString& v) { d->filename_ = v; }
@ -260,6 +264,8 @@ class Song {
float rating_; float rating_;
int playcount_; int playcount_;
int skipcount_;
int lastplayed_;
int length_; int length_;
int bitrate_; int bitrate_;