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:
parent
dd4afe9b06
commit
42e4c4a8db
@ -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>
|
||||||
|
@ -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);
|
||||||
|
4
data/schema/schema-18.sql
Normal file
4
data/schema/schema-18.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE %allsongstables ADD COLUMN skipcount INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE schema_version SET version=18;
|
||||||
|
|
@ -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,11 +448,34 @@ 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) {
|
||||||
|
// 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));
|
QSqlQuery query(db.exec(command));
|
||||||
if (CheckErrors(query.lastError()))
|
if (CheckErrors(query.lastError()))
|
||||||
qFatal("Unable to update music library database");
|
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()) {
|
||||||
|
@ -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_;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user