diff --git a/data/data.qrc b/data/data.qrc
index caffdb6fd..41f47825e 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -278,5 +278,6 @@
icons/22x22/rating.png
icons/32x32/rating.png
icons/48x48/rating.png
+ schema/schema-18.sql
diff --git a/data/schema/device-schema.sql b/data/schema/device-schema.sql
index e368a4c93..7e5f11f93 100644
--- a/data/schema/device-schema.sql
+++ b/data/schema/device-schema.sql
@@ -45,7 +45,9 @@ CREATE TABLE device_%deviceid_songs (
rating INTEGER,
forced_compilation_on 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);
diff --git a/data/schema/schema-18.sql b/data/schema/schema-18.sql
new file mode 100644
index 000000000..b3a2d6683
--- /dev/null
+++ b/data/schema/schema-18.sql
@@ -0,0 +1,4 @@
+ALTER TABLE %allsongstables ADD COLUMN skipcount INTEGER NOT NULL DEFAULT 0;
+
+UPDATE schema_version SET version=18;
+
diff --git a/src/core/database.cpp b/src/core/database.cpp
index 3d80929b6..b7e52aa2d 100644
--- a/src/core/database.cpp
+++ b/src/core/database.cpp
@@ -29,7 +29,8 @@
#include
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;
QMutex Database::sNextConnectionIdMutex;
@@ -447,12 +448,35 @@ void Database::ExecCommands(const QString &schema, QSqlDatabase &db) {
// Run each command
QStringList commands(schema.split(";\n\n"));
foreach (const QString& command, commands) {
- QSqlQuery query(db.exec(command));
- if (CheckErrors(query.lastError()))
- qFatal("Unable to update music library database");
+ // There are now lots of "songs" tables that need to have the same schema:
+ // songs, magnatune_songs, and device_*_songs. We allow a magic value
+ // 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) {
if (error.isValid()) {
qDebug() << error;
diff --git a/src/core/database.h b/src/core/database.h
index 39aadf1d6..0f73552f5 100644
--- a/src/core/database.h
+++ b/src/core/database.h
@@ -43,6 +43,7 @@ class Database : public QObject {
static const int kSchemaVersion;
static const char* kDatabaseFilename;
+ static const char* kMagicAllSongsTables;
void Stop() {}
@@ -58,6 +59,7 @@ class Database : public QObject {
private:
void UpdateDatabaseSchema(int version, QSqlDatabase& db);
+ QStringList SongsTables(QSqlDatabase& db) const;
QString directory_;
QMutex connect_mutex_;
diff --git a/src/core/song.cpp b/src/core/song.cpp
index 2a9610e36..4af39cf35 100644
--- a/src/core/song.cpp
+++ b/src/core/song.cpp
@@ -89,7 +89,7 @@ const QStringList Song::kColumns = QStringList()
<< "mtime" << "ctime" << "filesize" << "sampler" << "art_automatic"
<< "art_manual" << "filetype" << "playcount" << "lastplayed" << "rating"
<< "forced_compilation_on" << "forced_compilation_off"
- << "effective_compilation";
+ << "effective_compilation" << "skipcount";
const QString Song::kColumnSpec = Song::kColumns.join(", ");
const QString Song::kBindSpec = Prepend(":", Song::kColumns).join(", ");
@@ -151,6 +151,8 @@ Song::Private::Private()
forced_compilation_off_(false),
rating_(-1.0),
playcount_(0),
+ skipcount_(0),
+ lastplayed_(-1),
length_(-1),
bitrate_(-1),
samplerate_(-1),
@@ -459,7 +461,7 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
d->filetype_ = FileType(q.value(col + 24).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->forced_compilation_on_ = q.value(col + 28).toBool();
@@ -467,6 +469,8 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
// effective_compilation = 30
+ d->skipcount_ = q.value(col + 31).isNull() ? 0 : q.value(col + 31).toInt();
+
#undef tostr
#undef toint
#undef tofloat
@@ -508,6 +512,8 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->filetype_ = track->type2 ? Type_Mpeg : Type_Mp4;
d->rating_ = float(track->rating) / 100; // 100 = 20 * 5 stars
d->playcount_ = track->playcount;
+ d->skipcount_ = track->skipcount;
+ d->lastplayed_ = track->time_played;
d->filename_ = QString::fromLocal8Bit(track->ipod_path);
d->filename_.replace(':', '/');
@@ -538,6 +544,8 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
track->mediatype = 1; // Audio
track->rating = d->rating_ * 100; // 100 = 20 * 5 stars
track->playcount = d->playcount_;
+ track->skipcount = d->skipcount_;
+ track->time_played = d->lastplayed_;
}
#endif
@@ -905,7 +913,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
query->bindValue(":filetype", d->filetype_);
query->bindValue(":playcount", d->playcount_);
- query->bindValue(":lastplayed", -1); // TODO
+ query->bindValue(":lastplayed", intval(d->lastplayed_));
query->bindValue(":rating", intval(d->rating_));
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(":skipcount", d->skipcount_);
+
#undef intval
#undef notnullintval
}
diff --git a/src/core/song.h b/src/core/song.h
index 159d42906..79c2e8f1a 100644
--- a/src/core/song.h
+++ b/src/core/song.h
@@ -159,6 +159,8 @@ class Song {
}
float rating() const { return d->rating_; }
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 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_rating(float v) { d->rating_ = 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
void set_filename(const QString& v) { d->filename_ = v; }
@@ -260,6 +264,8 @@ class Song {
float rating_;
int playcount_;
+ int skipcount_;
+ int lastplayed_;
int length_;
int bitrate_;