Add source to songs and playlist_items

This commit is contained in:
Jonas Kvinge
2018-09-08 12:38:02 +02:00
parent 19b645d731
commit 6d686ee66a
48 changed files with 500 additions and 401 deletions

View File

@@ -52,7 +52,7 @@
#include "scopedtransaction.h"
const char *Database::kDatabaseFilename = "strawberry.db";
const int Database::kSchemaVersion = 2;
const int Database::kSchemaVersion = 3;
const char *Database::kMagicAllSongsTables = "%allsongstables";
int Database::sNextConnectionId = 1;

View File

@@ -293,14 +293,14 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
// Icons
qLog(Debug) << "Creating UI";
// Help menu
ui_->action_about_strawberry->setIcon(IconLoader::Load("strawberry"));
ui_->action_about_qt->setIcon(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"));
// Music menu
ui_->action_open_file->setIcon(IconLoader::Load("document-open"));
ui_->action_open_cd->setIcon(IconLoader::Load("cd"));
ui_->action_previous_track->setIcon(IconLoader::Load("media-rewind"));
@@ -309,9 +309,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->action_stop_after_this_track->setIcon(IconLoader::Load("media-stop"));
ui_->action_next_track->setIcon(IconLoader::Load("media-forward"));
ui_->action_quit->setIcon(IconLoader::Load("application-exit"));
// Playlist
ui_->action_add_file->setIcon(IconLoader::Load("document-open"));
ui_->action_add_folder->setIcon(IconLoader::Load("document-open-folder"));
ui_->action_shuffle_mode->setIcon(IconLoader::Load("media-playlist-shuffle"));
@@ -324,11 +324,11 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->action_shuffle->setIcon(IconLoader::Load("media-playlist-shuffle"));
ui_->action_remove_duplicates->setIcon(IconLoader::Load("list-remove"));
ui_->action_remove_unavailable->setIcon(IconLoader::Load("list-remove"));
//ui_->action_remove_from_playlist->setIcon(IconLoader::Load("list-remove"));
// Configure
ui_->action_cover_manager->setIcon(IconLoader::Load("document-download"));
ui_->action_queue_manager->setIcon(IconLoader::Load("footsteps"));
ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename"));
@@ -452,9 +452,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->playlist->view(), SIGNAL(BackgroundPropertyChanged()), SLOT(RefreshStyleSheet()));
connect(ui_->track_slider, SIGNAL(ValueChangedSeconds(int)), app_->player(), SLOT(SeekTo(int)));
// Context connections
connect(context_view_->albums(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
// Collection connections
@@ -1848,7 +1848,7 @@ void MainWindow::EditFileTags(const QList<QUrl> &urls) {
Song song;
song.set_url(url);
song.set_valid(true);
song.set_filetype(Song::Type_MPEG);
song.set_filetype(Song::FileType_MPEG);
songs << song;
}

View File

@@ -71,7 +71,7 @@ class MusicStorage {
virtual QString LocalPath() const { return QString(); }
virtual TranscodeMode GetTranscodeMode() const { return Transcode_Never; }
virtual Song::FileType GetTranscodeFormat() const { return Song::Type_Unknown; }
virtual Song::FileType GetTranscodeFormat() const { return Song::FileType_Unknown; }
virtual bool GetSupportedFiletypes(QList<Song::FileType>* ret) { return true; }
virtual bool StartCopy(QList<Song::FileType>* supported_types) { return true;}

View File

@@ -154,7 +154,7 @@ void Organise::ProcessSomeFiles() {
else {
// Figure out if we need to transcode it
Song::FileType dest_type = CheckTranscode(song.filetype());
if (dest_type != Song::Type_Unknown) {
if (dest_type != Song::FileType_Unknown) {
// Get the preset
TranscoderPreset preset = Transcoder::PresetForFileType(dest_type);
qLog(Debug) << "Transcoding with" << preset.name_;
@@ -206,28 +206,28 @@ void Organise::ProcessSomeFiles() {
Song::FileType Organise::CheckTranscode(Song::FileType original_type) const {
//if (original_type == Song::Type_Stream) return Song::Type_Unknown;
if (original_type == Song::FileType_Stream) return Song::FileType_Unknown;
const MusicStorage::TranscodeMode mode = destination_->GetTranscodeMode();
const Song::FileType format = destination_->GetTranscodeFormat();
switch (mode) {
case MusicStorage::Transcode_Never:
return Song::Type_Unknown;
return Song::FileType_Unknown;
case MusicStorage::Transcode_Always:
if (original_type == format) return Song::Type_Unknown;
if (original_type == format) return Song::FileType_Unknown;
return format;
case MusicStorage::Transcode_Unsupported:
if (supported_filetypes_.isEmpty() || supported_filetypes_.contains(original_type)) return Song::Type_Unknown;
if (supported_filetypes_.isEmpty() || supported_filetypes_.contains(original_type)) return Song::FileType_Unknown;
if (format != Song::Type_Unknown) return format;
if (format != Song::FileType_Unknown) return format;
// The user hasn't visited the device properties page yet to set a preferred format for the device, so we have to pick the best available one.
return Transcoder::PickBestFormat(supported_filetypes_);
}
return Song::Type_Unknown;
return Song::FileType_Unknown;
}

View File

@@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,6 +39,7 @@
#include <QRegExp>
#include <QUrl>
#include <QImage>
#include <QIcon>
#include <QTextCodec>
#include <QSqlQuery>
#include <QtDebug>
@@ -52,6 +54,7 @@
#include "core/logging.h"
#include "core/messagehandler.h"
#include "core/iconloader.h"
#include "engine/enginebase.h"
#include "timeconstants.h"
@@ -86,6 +89,7 @@ const QStringList Song::kColumns = QStringList() << "title"
<< "samplerate"
<< "bitdepth"
<< "source"
<< "directory_id"
<< "filename"
<< "filetype"
@@ -167,6 +171,7 @@ struct Song::Private : public QSharedData {
int samplerate_;
int bitdepth_;
Source source_;
int directory_id_;
QString basefilename_;
QUrl url_;
@@ -210,14 +215,16 @@ Song::Private::Private()
end_(-1),
bitrate_(-1),
samplerate_(-1),
bitdepth_(-1),
source_(Source_Unknown),
directory_id_(-1),
filetype_(Type_Unknown),
filetype_(FileType_Unknown),
filesize_(-1),
mtime_(-1),
ctime_(-1),
unavailable_(false),
playcount_(0),
skipcount_(0),
lastplayed_(-1),
@@ -283,6 +290,7 @@ qint64 Song::length_nanosec() const { return d->end_ - d->beginning_; }
int Song::bitrate() const { return d->bitrate_; }
int Song::samplerate() const { return d->samplerate_; }
int Song::bitdepth() const { return d->bitdepth_; }
Song::Source Song::source() const { return d->source_; }
int Song::directory_id() const { return d->directory_id_; }
const QUrl &Song::url() const { return d->url_; }
const QString &Song::basefilename() const { return d->basefilename_; }
@@ -290,8 +298,8 @@ uint Song::mtime() const { return d->mtime_; }
uint Song::ctime() const { return d->ctime_; }
int Song::filesize() const { return d->filesize_; }
Song::FileType Song::filetype() const { return d->filetype_; }
bool Song::is_stream() const { return d->filetype_ == Type_Stream; }
bool Song::is_cdda() const { return d->filetype_ == Type_CDDA; }
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal; }
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
bool Song::is_collection_song() const {
return !is_cdda() && !is_stream() && id() != -1;
}
@@ -331,6 +339,7 @@ void Song::set_bitrate(int v) { d->bitrate_ = v; }
void Song::set_samplerate(int v) { d->samplerate_ = v; }
void Song::set_bitdepth(int v) { d->bitdepth_ = v; }
void Song::set_source(Source v) { d->source_ = v; }
void Song::set_directory_id(int v) { d->directory_id_ = v; }
void Song::set_url(const QUrl &v) {
if (Application::kIsPortable) {
@@ -366,39 +375,93 @@ QString Song::JoinSpec(const QString &table) {
return Utilities::Prepend(table + ".", kColumns).join(", ");
}
QString Song::TextForFiletype(FileType type) {
QString Song::TextForSource(Source source) {
switch (type) {
case Song::Type_WAV: return QObject::tr("Wav");
case Song::Type_FLAC: return QObject::tr("FLAC");
case Song::Type_WavPack: return QObject::tr("WavPack");
case Song::Type_OggFlac: return QObject::tr("Ogg FLAC");
case Song::Type_OggVorbis: return QObject::tr("Ogg Vorbis");
case Song::Type_OggOpus: return QObject::tr("Ogg Opus");
case Song::Type_OggSpeex: return QObject::tr("Ogg Speex");
case Song::Type_MPEG: return QObject::tr("MP3");
case Song::Type_MP4: return QObject::tr("MP4 AAC");
case Song::Type_ASF: return QObject::tr("Windows Media audio");
case Song::Type_AIFF: return QObject::tr("AIFF");
case Song::Type_MPC: return QObject::tr("MPC");
case Song::Type_TrueAudio: return QObject::tr("TrueAudio");
case Song::Type_DSF: return QObject::tr("DSF"); // .dsf
case Song::Type_DSDIFF: return QObject::tr("DSDIFF"); // .dff
case Song::Type_CDDA: return QObject::tr("CDDA");
case Song::Type_Stream: return QObject::tr("Stream");
case Song::Type_Unknown:
default: return QObject::tr("Unknown");
switch (source) {
case Song::Source_LocalFile: return QObject::tr("File");
case Song::Source_Collection: return QObject::tr("Collection");
case Song::Source_CDDA: return QObject::tr("CD");
case Song::Source_Device: return QObject::tr("Device");
case Song::Source_Stream: return QObject::tr("Stream");
case Song::Source_Tidal: return QObject::tr("Tidal");
default: return QObject::tr("Unknown");
}
}
QIcon Song::IconForSource(Source source) {
switch (source) {
case Song::Source_LocalFile: return IconLoader::Load("folder-sound");
case Song::Source_Collection: return IconLoader::Load("vinyl");
case Song::Source_CDDA: return IconLoader::Load("cd");
case Song::Source_Device: return IconLoader::Load("device");
case Song::Source_Stream: return IconLoader::Load("applications-internet");
case Song::Source_Tidal: return IconLoader::Load("tidal");
default: return IconLoader::Load("edit-delete");
}
}
QString Song::TextForFiletype(FileType filetype) {
switch (filetype) {
case Song::FileType_WAV: return QObject::tr("Wav");
case Song::FileType_FLAC: return QObject::tr("FLAC");
case Song::FileType_WavPack: return QObject::tr("WavPack");
case Song::FileType_OggFlac: return QObject::tr("Ogg FLAC");
case Song::FileType_OggVorbis: return QObject::tr("Ogg Vorbis");
case Song::FileType_OggOpus: return QObject::tr("Ogg Opus");
case Song::FileType_OggSpeex: return QObject::tr("Ogg Speex");
case Song::FileType_MPEG: return QObject::tr("MP3");
case Song::FileType_MP4: return QObject::tr("MP4 AAC");
case Song::FileType_ASF: return QObject::tr("Windows Media audio");
case Song::FileType_AIFF: return QObject::tr("AIFF");
case Song::FileType_MPC: return QObject::tr("MPC");
case Song::FileType_TrueAudio: return QObject::tr("TrueAudio");
case Song::FileType_DSF: return QObject::tr("DSF");
case Song::FileType_DSDIFF: return QObject::tr("DSDIFF");
case Song::FileType_CDDA: return QObject::tr("CDDA");
case Song::FileType_Stream: return QObject::tr("Stream");
case Song::FileType_Unknown:
default: return QObject::tr("Unknown");
}
}
QIcon Song::IconForFiletype(FileType filetype) {
switch (filetype) {
case Song::FileType_WAV: return IconLoader::Load("wav");
case Song::FileType_FLAC: return IconLoader::Load("flac");
case Song::FileType_WavPack: return IconLoader::Load("wavpack");
case Song::FileType_OggFlac: return IconLoader::Load("flac");
case Song::FileType_OggVorbis: return IconLoader::Load("vorbis");
case Song::FileType_OggOpus: return IconLoader::Load("opus");
case Song::FileType_OggSpeex: return IconLoader::Load("speex");
case Song::FileType_MPEG: return IconLoader::Load("mp3");
case Song::FileType_MP4: return IconLoader::Load("mp4");
case Song::FileType_ASF: return IconLoader::Load("wma");
case Song::FileType_AIFF: return IconLoader::Load("aiff");
case Song::FileType_MPC: return IconLoader::Load("mpc");
case Song::FileType_TrueAudio: return IconLoader::Load("trueaudio");
case Song::FileType_DSF: return IconLoader::Load("dsf");
case Song::FileType_DSDIFF: return IconLoader::Load("dsd");
case Song::FileType_CDDA: return IconLoader::Load("cd");
case Song::FileType_Stream: return IconLoader::Load("applications-internet");
case Song::FileType_Unknown:
default: return IconLoader::Load("edit-delete");
}
}
bool Song::IsFileLossless() const {
switch (filetype()) {
case Song::Type_WAV:
case Song::Type_FLAC:
case Song::Type_OggFlac:
case Song::Type_WavPack:
case Song::Type_AIFF:
case Song::FileType_WAV:
case Song::FileType_FLAC:
case Song::FileType_OggFlac:
case Song::FileType_WavPack:
case Song::FileType_AIFF:
return true;
default:
return false;
@@ -407,20 +470,20 @@ bool Song::IsFileLossless() const {
Song::FileType Song::FiletypeByExtension(QString ext) {
if (ext.toLower() == "wav" || ext.toLower() == "wave") return Song::Type_WAV;
else if (ext.toLower() == "flac") return Song::Type_FLAC;
else if (ext.toLower() == "wavpack" || ext.toLower() == "wv") return Song::Type_WavPack;
else if (ext.toLower() == "ogg" || ext.toLower() == "oga") return Song::Type_OggVorbis;
else if (ext.toLower() == "opus") return Song::Type_OggOpus;
else if (ext.toLower() == "speex" || ext.toLower() == "spx") return Song::Type_OggSpeex;
else if (ext.toLower() == "mp3") return Song::Type_MPEG;
else if (ext.toLower() == "mp4" || ext.toLower() == "m4a" || ext.toLower() == "aac") return Song::Type_MP4;
else if (ext.toLower() == "asf" || ext.toLower() == "wma") return Song::Type_ASF;
else if (ext.toLower() == "aiff" || ext.toLower() == "aif" || ext.toLower() == "aifc") return Song::Type_AIFF;
else if (ext.toLower() == "mpc" || ext.toLower() == "mp+" || ext.toLower() == "mpp") return Song::Type_MPC;
else if (ext.toLower() == "dsf") return Song::Type_DSF;
else if (ext.toLower() == "dsd" || ext.toLower() == "dff") return Song::Type_DSDIFF;
else return Song::Type_Unknown;
if (ext.toLower() == "wav" || ext.toLower() == "wave") return Song::FileType_WAV;
else if (ext.toLower() == "flac") return Song::FileType_FLAC;
else if (ext.toLower() == "wavpack" || ext.toLower() == "wv") return Song::FileType_WavPack;
else if (ext.toLower() == "ogg" || ext.toLower() == "oga") return Song::FileType_OggVorbis;
else if (ext.toLower() == "opus") return Song::FileType_OggOpus;
else if (ext.toLower() == "speex" || ext.toLower() == "spx") return Song::FileType_OggSpeex;
else if (ext.toLower() == "mp3") return Song::FileType_MPEG;
else if (ext.toLower() == "mp4" || ext.toLower() == "m4a" || ext.toLower() == "aac") return Song::FileType_MP4;
else if (ext.toLower() == "asf" || ext.toLower() == "wma") return Song::FileType_ASF;
else if (ext.toLower() == "aiff" || ext.toLower() == "aif" || ext.toLower() == "aifc") return Song::FileType_AIFF;
else if (ext.toLower() == "mpc" || ext.toLower() == "mp+" || ext.toLower() == "mpp") return Song::FileType_MPC;
else if (ext.toLower() == "dsf") return Song::FileType_DSF;
else if (ext.toLower() == "dsd" || ext.toLower() == "dff") return Song::FileType_DSDIFF;
else return Song::FileType_Unknown;
}
@@ -547,7 +610,7 @@ void Song::ToProtobuf(pb::tagreader::SongMetadata *pb) const {
pb->set_filesize(d->filesize_);
pb->set_suspicious_tags(d->suspicious_tags_);
pb->set_art_automatic(DataCommaSizeFromQString(d->art_automatic_));
pb->set_filetype(static_cast<pb::tagreader::SongMetadata_Type>(d->filetype_));
pb->set_filetype(static_cast<pb::tagreader::SongMetadata_FileType>(d->filetype_));
}
#define tostr(n) (q.value(n).isNull() ? QString::null : q.value(n).toString())
@@ -635,6 +698,9 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
d->bitdepth_ = toint(x);
}
else if (Song::kColumns.value(i) == "source") {
d->source_ = Source(q.value(x).toInt());
}
else if (Song::kColumns.value(i) == "directory_id") {
d->directory_id_ = toint(x);
}
@@ -721,8 +787,10 @@ void Song::InitFromFilePartial(const QString &filename) {
QString suffix = info.suffix().toLower();
TagLib::FileRef fileref(filename.toUtf8().constData());
//if (TagLib::FileRef::defaultFileExtensions().contains(suffix.toUtf8().constData())) {
if (fileref.file()) d->valid_ = true;
if (fileref.file()) {
d->valid_ = true;
d->source_ = Source_LocalFile;
}
else {
d->valid_ = false;
qLog(Error) << "File" << filename << "is not recognized by TagLib as a valid audio file.";
@@ -772,6 +840,7 @@ void Song::InitFromItdb(const Itdb_Track *track, const QString &prefix) {
d->samplerate_ = track->samplerate;
d->bitdepth_ = -1; //track->bitdepth;
d->source_ = Source_Device;
QString filename = QString::fromLocal8Bit(track->ipod_path);
filename.replace(':', '/');
if (prefix.contains("://")) {
@@ -780,8 +849,8 @@ void Song::InitFromItdb(const Itdb_Track *track, const QString &prefix) {
set_url(QUrl::fromLocalFile(prefix + filename));
}
d->basefilename_ = QFileInfo(filename).fileName();
d->filetype_ = track->type2 ? Type_MPEG : Type_MP4;
d->filetype_ = track->type2 ? FileType_MPEG : FileType_MP4;
d->filesize_ = track->size;
d->mtime_ = track->time_modified;
d->ctime_ = track->time_added;
@@ -814,7 +883,7 @@ void Song::ToItdb(Itdb_Track *track) const {
//track->bithdepth = d->bithdepth_;
track->type1 = 0;
track->type2 = d->filetype_ == Type_MP4 ? 0 : 1;
track->type2 = d->filetype_ == FileType_MP4 ? 0 : 1;
track->mediatype = 1; // Audio
track->size = d->filesize_;
track->time_modified = d->mtime_;
@@ -854,18 +923,20 @@ void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) {
d->playcount_ = track->usecount;
switch (track->filetype) {
case LIBMTP_FILETYPE_WAV: d->filetype_ = Type_WAV; break;
case LIBMTP_FILETYPE_MP3: d->filetype_ = Type_MPEG; break;
case LIBMTP_FILETYPE_WMA: d->filetype_ = Type_ASF; break;
case LIBMTP_FILETYPE_OGG: d->filetype_ = Type_OggVorbis; break;
case LIBMTP_FILETYPE_MP4: d->filetype_ = Type_MP4; break;
case LIBMTP_FILETYPE_AAC: d->filetype_ = Type_MP4; break;
case LIBMTP_FILETYPE_FLAC: d->filetype_ = Type_OggFlac; break;
case LIBMTP_FILETYPE_MP2: d->filetype_ = Type_MPEG; break;
case LIBMTP_FILETYPE_M4A: d->filetype_ = Type_MP4; break;
default: d->filetype_ = Type_Unknown; break;
case LIBMTP_FILETYPE_WAV: d->filetype_ = FileType_WAV; break;
case LIBMTP_FILETYPE_MP3: d->filetype_ = FileType_MPEG; break;
case LIBMTP_FILETYPE_WMA: d->filetype_ = FileType_ASF; break;
case LIBMTP_FILETYPE_OGG: d->filetype_ = FileType_OggVorbis; break;
case LIBMTP_FILETYPE_MP4: d->filetype_ = FileType_MP4; break;
case LIBMTP_FILETYPE_AAC: d->filetype_ = FileType_MP4; break;
case LIBMTP_FILETYPE_FLAC: d->filetype_ = FileType_OggFlac; break;
case LIBMTP_FILETYPE_MP2: d->filetype_ = FileType_MPEG; break;
case LIBMTP_FILETYPE_M4A: d->filetype_ = FileType_MP4; break;
default: d->filetype_ = FileType_Unknown; break;
}
d->source_ = Source_Device;
}
void Song::ToMTP(LIBMTP_track_t *track) const {
@@ -897,15 +968,15 @@ void Song::ToMTP(LIBMTP_track_t *track) const {
track->usecount = d->playcount_;
switch (d->filetype_) {
case Type_ASF: track->filetype = LIBMTP_FILETYPE_ASF; break;
case Type_MP4: track->filetype = LIBMTP_FILETYPE_MP4; break;
case Type_MPEG: track->filetype = LIBMTP_FILETYPE_MP3; break;
case Type_FLAC:
case Type_OggFlac: track->filetype = LIBMTP_FILETYPE_FLAC; break;
case Type_OggSpeex:
case Type_OggVorbis: track->filetype = LIBMTP_FILETYPE_OGG; break;
case Type_WAV: track->filetype = LIBMTP_FILETYPE_WAV; break;
default: track->filetype = LIBMTP_FILETYPE_UNDEF_AUDIO; break;
case FileType_ASF: track->filetype = LIBMTP_FILETYPE_ASF; break;
case FileType_MP4: track->filetype = LIBMTP_FILETYPE_MP4; break;
case FileType_MPEG: track->filetype = LIBMTP_FILETYPE_MP3; break;
case FileType_FLAC:
case FileType_OggFlac: track->filetype = LIBMTP_FILETYPE_FLAC; break;
case FileType_OggSpeex:
case FileType_OggVorbis: track->filetype = LIBMTP_FILETYPE_OGG; break;
case FileType_WAV: track->filetype = LIBMTP_FILETYPE_WAV; break;
default: track->filetype = LIBMTP_FILETYPE_UNDEF_AUDIO; break;
}
}
@@ -965,6 +1036,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
query->bindValue(":samplerate", intval(d->samplerate_));
query->bindValue(":bitdepth", intval(d->bitdepth_));
query->bindValue(":source", notnullintval(d->source_));
query->bindValue(":directory_id", notnullintval(d->directory_id_));
if (Application::kIsPortable && Utilities::UrlOnSameDriveAsStrawberry(d->url_)) {
@@ -1103,7 +1175,7 @@ bool Song::IsMetadataEqual(const Song &other) const {
}
bool Song::IsEditable() const {
return d->valid_ && !d->url_.isEmpty() && !is_stream() && d->filetype_ != Type_Unknown && !has_cue();
return d->valid_ && !d->url_.isEmpty() && !is_stream() && d->source_ != Source_Unknown && d->filetype_ != FileType_Unknown && !has_cue();
}
bool Song::operator==(const Song &other) const {

View File

@@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +38,7 @@
#include <QRegExp>
#include <QUrl>
#include <QImage>
#include <QIcon>
#include <QTextCodec>
#include <QSqlQuery>
@@ -87,29 +89,48 @@ class Song {
// Don't change these values - they're stored in the database, and defined in the tag reader protobuf.
// If a new lossless file is added, also add it to IsFileLossless().
enum FileType {
Type_Unknown = 0,
Type_WAV = 1,
Type_FLAC = 2,
Type_WavPack = 3,
Type_OggFlac = 4,
Type_OggVorbis = 5,
Type_OggOpus = 6,
Type_OggSpeex = 7,
Type_MPEG = 8,
Type_MP4 = 9,
Type_ASF = 10,
Type_AIFF = 11,
Type_MPC = 12,
Type_TrueAudio = 13,
Type_DSF = 14,
Type_DSDIFF = 15,
Type_CDDA = 90,
Type_Stream = 91,
enum Source {
Source_Unknown = 0,
Source_LocalFile = 1,
Source_Collection = 2,
Source_CDDA = 3,
Source_Device = 4,
Source_Stream = 5,
Source_Tidal = 6,
};
static QString TextForFiletype(FileType type);
enum FileType {
FileType_Unknown = 0,
FileType_WAV = 1,
FileType_FLAC = 2,
FileType_WavPack = 3,
FileType_OggFlac = 4,
FileType_OggVorbis = 5,
FileType_OggOpus = 6,
FileType_OggSpeex = 7,
FileType_MPEG = 8,
FileType_MP4 = 9,
FileType_ASF = 10,
FileType_AIFF = 11,
FileType_MPC = 12,
FileType_TrueAudio = 13,
FileType_DSF = 14,
FileType_DSDIFF = 15,
FileType_CDDA = 90,
FileType_Stream = 91,
};
static QString TextForSource(Source source);
static QIcon IconForSource(Source source);
static QString TextForFiletype(FileType filetype);
QIcon IconForFiletype(FileType filetype);
QString TextForSource() const { return TextForSource(source()); }
QIcon IconForSource() const { return IconForSource(source()); }
QString TextForFiletype() const { return TextForFiletype(filetype()); }
QIcon IconForFiletype(FileType filetype) const { return IconForFiletype(filetype); }
bool IsFileLossless() const;
static FileType FiletypeByExtension(QString ext);
@@ -182,6 +203,7 @@ class Song {
int samplerate() const;
int bitdepth() const;
Source source() const;
int directory_id() const;
const QUrl &url() const;
const QString &basefilename() const;
@@ -260,7 +282,8 @@ class Song {
void set_bitrate(int v);
void set_samplerate(int v);
void set_bitdepth(int v);
void set_source(Source v);
void set_directory_id(int v);
void set_url(const QUrl &v);
void set_basefilename(const QString &v);

View File

@@ -276,7 +276,7 @@ void SongLoader::EffectiveSongLoad(Song *song) {
if (!song) return;
if (song->filetype() != Song::Type_Unknown) {
if (song->filetype() != Song::FileType_Unknown) {
// Maybe we loaded the metadata already, for example from a cuesheet.
return;
}
@@ -335,7 +335,7 @@ void SongLoader::LoadLocalDirectory(const QString &filename) {
void SongLoader::AddAsRawStream() {
Song song;
song.set_valid(true);
song.set_filetype(Song::Type_Stream);
song.set_filetype(Song::FileType_Stream);
song.set_url(url_);
song.set_title(url_.toString());
songs_ << song;
@@ -481,7 +481,7 @@ GstPadProbeReturn SongLoader::DataReady(GstPad*, GstPadProbeInfo *info, gpointer
#ifdef HAVE_GSTREAMER
gboolean SongLoader::BusCallback(GstBus *, GstMessage *msg, gpointer self) {
SongLoader *instance = reinterpret_cast<SongLoader*>(self);
switch (GST_MESSAGE_TYPE(msg)) {