Fixed regression on artist/release artist handling + fixed bug when firing a signal on still connected but deleted listener
This commit is contained in:
@@ -65,3 +65,6 @@ __Note__: since _LMS_ stores hashed and salted passwords, it cannot handle the _
|
||||
|
||||
See [INSTALL.md](INSTALL.md) file.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please prepare your pull requests on the [develop](../../tree/develop) branch.
|
||||
|
||||
@@ -199,6 +199,7 @@
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode">Artist list mode</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.all-artists">All artists</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Album artists</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Track artists</message>
|
||||
<message id="Lms.Settings.subsonic-api">Subsonic API</message>
|
||||
<message id="Lms.Settings.transcode">Transcoding</message>
|
||||
<message id="Lms.Settings.transcode-bitrate">Transcode bitrate</message>
|
||||
|
||||
@@ -199,6 +199,7 @@
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode">Mode de listage des artistes</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.all-artists">Tous les artistes</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Tous les artistes d'album</message>
|
||||
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Tous les artistes de piste</message>
|
||||
<message id="Lms.Settings.subsonic-api">API Subsonic</message>
|
||||
<message id="Lms.Settings.transcode">Transcodage</message>
|
||||
<message id="Lms.Settings.transcode-bitrate">Bitrate du transcodage</message>
|
||||
|
||||
@@ -509,12 +509,13 @@ Track::getArtists(EnumSet<TrackArtistLinkType> linkTypes) const
|
||||
oss << ")";
|
||||
}
|
||||
|
||||
Wt::Dbo::Query<Artist::pointer> query {session()->query<Artist::pointer>(oss.str())
|
||||
.where("t.id = ?").bind(self()->id())};
|
||||
Wt::Dbo::Query<Artist::pointer> query {session()->query<Artist::pointer>(oss.str())};
|
||||
|
||||
for (TrackArtistLinkType type : linkTypes)
|
||||
query.bind(type);
|
||||
|
||||
query.where("t.id = ?").bind(self()->id());
|
||||
|
||||
Wt::Dbo::collection<Artist::pointer> res = query;
|
||||
return std::vector<Artist::pointer>(std::begin(res), std::end(res));
|
||||
}
|
||||
|
||||
@@ -132,8 +132,9 @@ class User : public Wt::Dbo::Dbo<User>
|
||||
// Do not change enum values!
|
||||
enum class SubsonicArtistListMode
|
||||
{
|
||||
AllArtists = 0,
|
||||
AllArtists = 0,
|
||||
ReleaseArtists = 1,
|
||||
TrackArtists = 2,
|
||||
};
|
||||
|
||||
static inline const std::size_t MinNameLength {3};
|
||||
|
||||
@@ -397,7 +397,7 @@ TagLibParser::parse(const std::filesystem::path& p, bool debug)
|
||||
}
|
||||
|
||||
track.album = getAlbum(properties);
|
||||
track.artists = getArtists(properties, {"ARTIST", "ARTISTS"}, {"ARTISTSORT"}, {"MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID"});
|
||||
track.artists = getArtists(properties, {"ARTISTS", "ARTIST"}, {"ARTISTSORT"}, {"MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID"});
|
||||
track.albumArtists = getArtists(properties, {"ALBUMARTIST"}, {"ALBUMARTISTSORT"}, {"MUSICBRAINZ_ALBUMARTISTID", "MUSICBRAINZ ALBUM ARTIST ID"});
|
||||
track.conductorArtists = getArtists(properties, {"CONDUCTOR"}, {""}, {});
|
||||
track.composerArtists = getArtists(properties, {"COMPOSER"}, {"COMPOSERSORT"}, {});
|
||||
|
||||
@@ -316,7 +316,8 @@ trackToResponseNode(const Track::pointer& track, Session& dbSession, const User:
|
||||
|
||||
trackResponse.setAttribute("coverArt", IdToString({Id::Type::Track, track.id()}));
|
||||
|
||||
auto artists {track->getArtists({TrackArtistLinkType::Artist})};
|
||||
const std::vector<Artist::pointer>& artists {track->getArtists({TrackArtistLinkType::Artist})};
|
||||
LMS_LOG(API_SUBSONIC, DEBUG) << "Artists count = " << artists.size();
|
||||
if (!artists.empty())
|
||||
{
|
||||
trackResponse.setAttribute("artist", getArtistNames(artists));
|
||||
@@ -954,6 +955,9 @@ handleGetArtistsRequest(RequestContext& context)
|
||||
case User::SubsonicArtistListMode::ReleaseArtists:
|
||||
linkType = TrackArtistLinkType::ReleaseArtist;
|
||||
break;
|
||||
case User::SubsonicArtistListMode::TrackArtists:
|
||||
linkType = TrackArtistLinkType::Artist;
|
||||
break;
|
||||
}
|
||||
|
||||
bool more {};
|
||||
@@ -1098,6 +1102,9 @@ handleGetIndexesRequest(RequestContext& context)
|
||||
case User::SubsonicArtistListMode::ReleaseArtists:
|
||||
linkType = TrackArtistLinkType::ReleaseArtist;
|
||||
break;
|
||||
case User::SubsonicArtistListMode::TrackArtists:
|
||||
linkType = TrackArtistLinkType::Artist;
|
||||
break;
|
||||
}
|
||||
|
||||
bool more {};
|
||||
|
||||
@@ -541,7 +541,7 @@ LmsApplication::createHome()
|
||||
{
|
||||
const std::string sessionId {LmsApp->sessionId()};
|
||||
|
||||
Service<Scanner::IMediaScanner>::get()->scanStarted().connect(this, [=] ()
|
||||
Service<Scanner::IMediaScanner>::get()->scanStarted().connect(this, [=]
|
||||
{
|
||||
Wt::WServer::instance()->post(sessionId, [=]
|
||||
{
|
||||
@@ -550,9 +550,9 @@ LmsApplication::createHome()
|
||||
});
|
||||
});
|
||||
|
||||
Service<Scanner::IMediaScanner>::get()->scanComplete().connect(this, [=] ()
|
||||
Service<Scanner::IMediaScanner>::get()->scanComplete().connect(this, [=]
|
||||
{
|
||||
Wt::WServer::instance()->post(sessionId, [=]
|
||||
Wt::WServer::instance()->post(sessionId, [this]
|
||||
{
|
||||
_events.dbScanned.emit();
|
||||
triggerUpdate();
|
||||
|
||||
@@ -333,6 +333,7 @@ class SettingsModel : public Wt::WFormModel
|
||||
_subsonicArtistListModeModel = std::make_shared<ValueStringModel<User::SubsonicArtistListMode>>();
|
||||
_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);
|
||||
}
|
||||
|
||||
bool _withOldPassword {};
|
||||
@@ -346,12 +347,12 @@ class SettingsModel : public Wt::WFormModel
|
||||
|
||||
SettingsView::SettingsView()
|
||||
{
|
||||
wApp->internalPathChanged().connect([=]
|
||||
wApp->internalPathChanged().connect(this, [this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
LmsApp->getMediaPlayer().settingsLoaded.connect([=]()
|
||||
LmsApp->getMediaPlayer().settingsLoaded.connect([this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
@@ -167,10 +167,10 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
DatabaseSettingsView::DatabaseSettingsView()
|
||||
{
|
||||
wApp->internalPathChanged().connect(std::bind([=]
|
||||
wApp->internalPathChanged().connect(this, [this]
|
||||
{
|
||||
refreshView();
|
||||
}));
|
||||
});
|
||||
|
||||
refreshView();
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ ScannerController::ScannerController()
|
||||
|
||||
auto onDbEvent = [&]() { refreshContents(); };
|
||||
|
||||
LmsApp->getEvents().dbScanStarted.connect(this, []()
|
||||
LmsApp->getEvents().dbScanStarted.connect(this, []
|
||||
{
|
||||
LmsApp->notifyMsg(MsgType::Info, Wt::WString::tr("Lms.Admin.Database.scan-launched"));
|
||||
});
|
||||
|
||||
@@ -242,7 +242,7 @@ class UserModel : public Wt::WFormModel
|
||||
|
||||
UserView::UserView()
|
||||
{
|
||||
wApp->internalPathChanged().connect([this]()
|
||||
wApp->internalPathChanged().connect(this, [this]()
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ UsersView::UsersView()
|
||||
LmsApp->setInternalPath("/admin/user", true);
|
||||
});
|
||||
|
||||
wApp->internalPathChanged().connect([this]()
|
||||
wApp->internalPathChanged().connect(this, [this]()
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
@@ -73,6 +73,12 @@ class ValueStringModel : public Wt::WStringListModel
|
||||
setData(rowCount() - 1, 0, str, Wt::ItemDataRole::Display);
|
||||
}
|
||||
|
||||
void
|
||||
clear()
|
||||
{
|
||||
removeRows(0, rowCount());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
@@ -50,12 +50,12 @@ Artist::Artist(Filters* filters)
|
||||
{
|
||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||
|
||||
LmsApp->internalPathChanged().connect([=]
|
||||
LmsApp->internalPathChanged().connect(this, [this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
filters->updated().connect([=]
|
||||
filters->updated().connect([this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
@@ -69,35 +69,14 @@ Artists::Artists(Filters* filters)
|
||||
}
|
||||
|
||||
_linkType = bindNew<Wt::WComboBox>("link-type");
|
||||
|
||||
{
|
||||
auto linkTypeModel {std::make_shared<ArtistLinkModel>()};
|
||||
EnumSet<Database::TrackArtistLinkType> usedLinkTypes;
|
||||
{
|
||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||
usedLinkTypes = Database::TrackArtistLink::getUsedTypes(LmsApp->getDbSession());
|
||||
}
|
||||
|
||||
auto addTypeIfUsed {[&](Database::TrackArtistLinkType linkType, std::string_view stringKey)
|
||||
{
|
||||
if (!usedLinkTypes.contains(linkType))
|
||||
return;
|
||||
|
||||
linkTypeModel->add(Wt::WString::tr(std::string {stringKey}), linkType);
|
||||
}};
|
||||
|
||||
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), {});
|
||||
addTypeIfUsed(TrackArtistLinkType::Artist, "Lms.Explore.Artists.linktype-artist");
|
||||
addTypeIfUsed(TrackArtistLinkType::ReleaseArtist, "Lms.Explore.Artists.linktype-releaseartist");
|
||||
addTypeIfUsed(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist");
|
||||
addTypeIfUsed(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer");
|
||||
|
||||
_linkType->setModel(linkTypeModel);
|
||||
}
|
||||
_linkType->setModel(std::make_shared<ArtistLinkModel>());
|
||||
_linkType->changed().connect([this] { refreshView(); });
|
||||
refreshArtistLinkTypes();
|
||||
|
||||
LmsApp->getEvents().dbScanned.connect(this, [this]
|
||||
{
|
||||
refreshArtistLinkTypes();
|
||||
});
|
||||
|
||||
_container = bindNew<Wt::WContainerWidget>("artists");
|
||||
hideLoadingIndicator();
|
||||
@@ -122,6 +101,37 @@ Artists::refreshView(Mode mode)
|
||||
refreshView();
|
||||
}
|
||||
|
||||
void
|
||||
Artists::refreshArtistLinkTypes()
|
||||
{
|
||||
std::shared_ptr<ArtistLinkModel> linkTypeModel {std::static_pointer_cast<ArtistLinkModel>(_linkType->model())};
|
||||
|
||||
EnumSet<Database::TrackArtistLinkType> usedLinkTypes;
|
||||
{
|
||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||
usedLinkTypes = Database::TrackArtistLink::getUsedTypes(LmsApp->getDbSession());
|
||||
}
|
||||
|
||||
auto addTypeIfUsed {[&](Database::TrackArtistLinkType linkType, std::string_view stringKey)
|
||||
{
|
||||
if (!usedLinkTypes.contains(linkType))
|
||||
return;
|
||||
|
||||
linkTypeModel->add(Wt::WString::tr(std::string {stringKey}), linkType);
|
||||
}};
|
||||
|
||||
linkTypeModel->clear();
|
||||
|
||||
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), {});
|
||||
addTypeIfUsed(TrackArtistLinkType::Artist, "Lms.Explore.Artists.linktype-artist");
|
||||
addTypeIfUsed(TrackArtistLinkType::ReleaseArtist, "Lms.Explore.Artists.linktype-releaseartist");
|
||||
addTypeIfUsed(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist");
|
||||
addTypeIfUsed(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer");
|
||||
addTypeIfUsed(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer");
|
||||
}
|
||||
|
||||
void
|
||||
Artists::displayLoadingIndicator()
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ class Artists : public Wt::WTemplate
|
||||
|
||||
void refreshView();
|
||||
void refreshView(Mode mode);
|
||||
void refreshArtistLinkTypes();
|
||||
void displayLoadingIndicator();
|
||||
void hideLoadingIndicator();
|
||||
void addSome();
|
||||
|
||||
@@ -113,7 +113,7 @@ Explore::Explore(Filters* filters)
|
||||
tracks->tracksAction.connect(this, &Explore::handleTracksAction);
|
||||
contentsStack->addWidget(std::move(tracks));
|
||||
|
||||
wApp->internalPathChanged().connect([=]
|
||||
wApp->internalPathChanged().connect(this, [=]
|
||||
{
|
||||
handleContentsPathChange(contentsStack);
|
||||
});
|
||||
|
||||
@@ -54,12 +54,12 @@ Release::Release(Filters* filters)
|
||||
{
|
||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||
|
||||
wApp->internalPathChanged().connect([=]
|
||||
wApp->internalPathChanged().connect(this, [this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
filters->updated().connect([=]
|
||||
filters->updated().connect([this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
|
||||
@@ -290,7 +290,7 @@ testSingleTrackSingleArtist(Session& session)
|
||||
|
||||
CHECK(track->getArtists({TrackArtistLinkType::Artist}).size() == 1);
|
||||
CHECK(track->getArtists({TrackArtistLinkType::ReleaseArtist}).empty());
|
||||
CHECK(track->getArtists({}).empty());
|
||||
CHECK(track->getArtists({}).size() == 1);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user