Implemented a Scrobbling service + ListenBrainz scrobbler. fixes #118

This commit is contained in:
emeric
2021-04-06 19:59:12 +02:00
parent c29c4d576a
commit acf81e3f1a
49 changed files with 1662 additions and 177 deletions
+73 -22
View File
@@ -31,6 +31,7 @@
#include "common/PasswordValidator.hpp"
#include "common/MandatoryValidator.hpp"
#include "common/UUIDValidator.hpp"
#include "common/ValueStringModel.hpp"
#include "auth/IPasswordService.hpp"
@@ -62,12 +63,15 @@ class SettingsModel : public Wt::WFormModel
static inline const Field SubsonicTranscodeEnableField {"subsonic-transcode-enable"};
static inline const Field SubsonicTranscodeFormatField {"subsonic-transcode-format"};
static inline const Field SubsonicTranscodeBitrateField {"subsonic-transcode-bitrate"};
static inline const Field ScrobblerField {"scrobbler"};
static inline const Field ListenBrainzTokenField {"listenbrainz-token"};
static inline const Field PasswordOldField {"password-old"};
static inline const Field PasswordField {"password"};
static inline const Field PasswordConfirmField {"password-confirm"};
using TranscodeModeModel = ValueStringModel<MediaPlayer::Settings::Transcode::Mode>;
using ReplayGainModeModel = ValueStringModel<MediaPlayer::Settings::ReplayGain::Mode>;
using ScrobblerModel = ValueStringModel<Scrobbler>;
SettingsModel(::Auth::IPasswordService* authPasswordService, bool withOldPassword)
: _authPasswordService {authPasswordService}
@@ -85,6 +89,9 @@ class SettingsModel : public Wt::WFormModel
addField(SubsonicTranscodeEnableField);
addField(SubsonicTranscodeBitrateField);
addField(SubsonicTranscodeFormatField);
addField(ScrobblerField);
addField(ListenBrainzTokenField);
setValidator(ListenBrainzTokenField, createUUIDValidator());
if (_authPasswordService)
{
@@ -103,7 +110,6 @@ class SettingsModel : public Wt::WFormModel
setValidator(TranscodeBitrateField, createMandatoryValidator());
setValidator(TranscodeFormatField, createMandatoryValidator());
setValidator(ReplayGainModeField, createMandatoryValidator());
auto createPreAmpValidator = []
{
auto preampGainValidator {std::make_unique<Wt::WDoubleValidator>()};
@@ -119,11 +125,12 @@ class SettingsModel : public Wt::WFormModel
loadData();
}
std::shared_ptr<TranscodeModeModel> getTranscodeModeModel() { return _transcodeModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodeBitrateModel() { return _transcodeBitrateModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodeFormatModel() { return _transcodeFormatModel; }
std::shared_ptr<ReplayGainModeModel> getReplayGainModeModel() { return _replayGainModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getSubsonicArtistListModeModel() { return _subsonicArtistListModeModel; }
std::shared_ptr<TranscodeModeModel> getTranscodeModeModel() { return _transcodeModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodeBitrateModel() { return _transcodeBitrateModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodeFormatModel() { return _transcodeFormatModel; }
std::shared_ptr<ReplayGainModeModel> getReplayGainModeModel() { return _replayGainModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getSubsonicArtistListModeModel() { return _subsonicArtistListModeModel; }
std::shared_ptr<ScrobblerModel> getScrobblerModel() { return _scrobblerModel; }
void saveData()
{
@@ -174,11 +181,19 @@ class SettingsModel : public Wt::WFormModel
auto subsonicTranscodeFormatRow {_transcodeFormatModel->getRowFromString(valueText(SubsonicTranscodeFormatField))};
if (subsonicTranscodeFormatRow)
user.modify()->setSubsonicTranscodeFormat(_transcodeFormatModel->getValue(*subsonicTranscodeFormatRow));
auto subsonicArtistListModeRow {_subsonicArtistListModeModel->getRowFromString(valueText(SubsonicArtistListModeField))};
if (subsonicArtistListModeRow)
user.modify()->setSubsonicArtistListMode(_subsonicArtistListModeModel->getValue(*subsonicArtistListModeRow));
}
auto subsonicArtistListModeRow {_subsonicArtistListModeModel->getRowFromString(valueText(SubsonicArtistListModeField))};
if (subsonicArtistListModeRow)
user.modify()->setSubsonicArtistListMode(_subsonicArtistListModeModel->getValue(*subsonicArtistListModeRow));
{
if (auto scrobblerRow {_scrobblerModel->getRowFromString(valueText(ScrobblerField))})
user.modify()->setScrobbler(_scrobblerModel->getValue(*scrobblerRow));
user.modify()->setListenBrainzToken(UUID::fromString(Wt::asString(value(ListenBrainzTokenField)).toUTF8()));
}
if (_authPasswordService && !valueText(PasswordField).empty())
{
@@ -225,17 +240,30 @@ class SettingsModel : public Wt::WFormModel
setReadOnly(SubsonicTranscodeBitrateField, true);
}
auto subsonicTranscodeBitrateRow {_transcodeBitrateModel->getRowFromValue(user->getSubsonicTranscodeBitrate())};
if (subsonicTranscodeBitrateRow)
setValue(SubsonicTranscodeBitrateField, _transcodeBitrateModel->getString(*subsonicTranscodeBitrateRow));
{
auto subsonicTranscodeBitrateRow {_transcodeBitrateModel->getRowFromValue(user->getSubsonicTranscodeBitrate())};
if (subsonicTranscodeBitrateRow)
setValue(SubsonicTranscodeBitrateField, _transcodeBitrateModel->getString(*subsonicTranscodeBitrateRow));
auto subsonicTranscodeFormatRow {_transcodeFormatModel->getRowFromValue(user->getSubsonicTranscodeFormat())};
if (subsonicTranscodeFormatRow)
setValue(SubsonicTranscodeFormatField, _transcodeFormatModel->getString(*subsonicTranscodeFormatRow));
auto subsonicTranscodeFormatRow {_transcodeFormatModel->getRowFromValue(user->getSubsonicTranscodeFormat())};
if (subsonicTranscodeFormatRow)
setValue(SubsonicTranscodeFormatField, _transcodeFormatModel->getString(*subsonicTranscodeFormatRow));
auto subsonicArtistListModeRow {_subsonicArtistListModeModel->getRowFromValue(user->getSubsonicArtistListMode())};
if (subsonicArtistListModeRow)
setValue(SubsonicArtistListModeField, _subsonicArtistListModeModel->getString(*subsonicArtistListModeRow));
auto subsonicArtistListModeRow {_subsonicArtistListModeModel->getRowFromValue(user->getSubsonicArtistListMode())};
if (subsonicArtistListModeRow)
setValue(SubsonicArtistListModeField, _subsonicArtistListModeModel->getString(*subsonicArtistListModeRow));
}
{
if (auto scrobblerRow {_scrobblerModel->getRowFromValue(user->getScrobbler())})
setValue(ScrobblerField, _scrobblerModel->getString(*scrobblerRow));
if (auto listenBrainzToken {user->getListenBrainzToken()})
{
LMS_LOG(UI, DEBUG) << "Read listenBrainzToken! value = " << listenBrainzToken->getAsString();
setValue(ListenBrainzTokenField, Wt::WString::fromUTF8( std::string {listenBrainzToken->getAsString()}));
}
}
}
private:
@@ -309,16 +337,21 @@ class SettingsModel : public Wt::WFormModel
_subsonicArtistListModeModel->add(Wt::WString::tr("Lms.Settings.subsonic-artist-list-mode.all-artists"), User::SubsonicArtistListMode::AllArtists);
_subsonicArtistListModeModel->add(Wt::WString::tr("Lms.Settings.subsonic-artist-list-mode.release-artists"), User::SubsonicArtistListMode::ReleaseArtists);
_subsonicArtistListModeModel->add(Wt::WString::tr("Lms.Settings.subsonic-artist-list-mode.track-artists"), User::SubsonicArtistListMode::TrackArtists);
_scrobblerModel = std::make_shared<ValueStringModel<Scrobbler>>();
_scrobblerModel->add(Wt::WString::tr("Lms.Settings.scrobbling.scrobbler.internal"), Scrobbler::Internal);
_scrobblerModel->add(Wt::WString::tr("Lms.Settings.scrobbling.scrobbler.listenbrainz"), Scrobbler::ListenBrainz);
}
::Auth::IPasswordService* _authPasswordService {};
bool _withOldPassword {};
std::shared_ptr<TranscodeModeModel> _transcodeModeModel;
std::shared_ptr<TranscodeModeModel> _transcodeModeModel;
std::shared_ptr<ValueStringModel<Bitrate>> _transcodeBitrateModel;
std::shared_ptr<ValueStringModel<AudioFormat>> _transcodeFormatModel;
std::shared_ptr<ValueStringModel<AudioFormat>> _transcodeFormatModel;
std::shared_ptr<ReplayGainModeModel> _replayGainModeModel;
std::shared_ptr<ValueStringModel<User::SubsonicArtistListMode>> _subsonicArtistListModeModel;
std::shared_ptr<ScrobblerModel> _scrobblerModel;
};
SettingsView::SettingsView()
@@ -473,11 +506,11 @@ SettingsView::refreshView()
t->setFormWidget(SettingsModel::SubsonicTranscodeBitrateField, std::move(transcodeBitrate));
// Artist list mode
auto artistListMode = std::make_unique<Wt::WComboBox>();
auto artistListMode {std::make_unique<Wt::WComboBox>()};
artistListMode->setModel(model->getSubsonicArtistListModeModel());
t->setFormWidget(SettingsModel::SubsonicArtistListModeField, std::move(artistListMode));
transcodeRaw->changed().connect([=]()
transcodeRaw->changed().connect([=]
{
const bool enable {transcodeRaw->checkState() == Wt::CheckState::Checked};
model->setReadOnly(SettingsModel::SubsonicTranscodeFormatField, !enable);
@@ -487,6 +520,24 @@ SettingsView::refreshView()
});
}
// Scrobbling
{
auto scrobbler {std::make_unique<Wt::WComboBox>()};
scrobbler->setModel(model->getScrobblerModel());
auto* scrobblerRaw {scrobbler.get()};
t->setFormWidget(SettingsModel::ScrobblerField, std::move(scrobbler));
auto listenbrainzToken {std::make_unique<Wt::WLineEdit>()};
t->setFormWidget(SettingsModel::ListenBrainzTokenField, std::move(listenbrainzToken));
scrobblerRaw->activated().connect([=](int row)
{
const bool enable {model->getScrobblerModel()->getValue(row) == Scrobbler::ListenBrainz};
model->setReadOnly(SettingsModel::ListenBrainzTokenField, !enable);
t->updateModel(model.get());
t->updateView(model.get());
});
}
// Buttons
Wt::WPushButton *saveBtn {t->bindWidget("apply-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.apply")))};
Wt::WPushButton *discardBtn {t->bindWidget("discard-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.discard")))};