Remove special None handling and video
This commit is contained in:
@@ -8,14 +8,6 @@ AC_LANG_CPLUSPLUS
|
|||||||
# Checks for programs
|
# Checks for programs
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
|
|
||||||
AC_ARG_ENABLE([video], AS_HELP_STRING([--enable-video],
|
|
||||||
[Enable Video support. Default to no.])],
|
|
||||||
[enable_video="$enableval"],
|
|
||||||
[enable_video="no"])
|
|
||||||
|
|
||||||
AM_CONDITIONAL([VIDEO], [test x$enable_video = xyes])
|
|
||||||
AS_IF([test x$enable_video = xyes], [AC_DEFINE(HAVE_VIDEO, [1], [Enable Video support])])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(IMAGEMAGICKXX, "ImageMagick++", [ HAVE_IMAGEMAGICKXX=yes ], [ ])
|
PKG_CHECK_MODULES(IMAGEMAGICKXX, "ImageMagick++", [ HAVE_IMAGEMAGICKXX=yes ], [ ])
|
||||||
if test -n "$HAVE_IMAGEMAGICKXX"; then
|
if test -n "$HAVE_IMAGEMAGICKXX"; then
|
||||||
MAGICKXX_CFLAGS="$IMAGEMAGICKXX_CFLAGS"
|
MAGICKXX_CFLAGS="$IMAGEMAGICKXX_CFLAGS"
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/database/SqlQuery.cpp \
|
$(srcdir)/database/SqlQuery.cpp \
|
||||||
$(srcdir)/database/Track.cpp \
|
$(srcdir)/database/Track.cpp \
|
||||||
$(srcdir)/database/User.cpp \
|
$(srcdir)/database/User.cpp \
|
||||||
$(srcdir)/database/Video.cpp \
|
|
||||||
$(srcdir)/database/updater/DatabaseUpdater.cpp \
|
$(srcdir)/database/updater/DatabaseUpdater.cpp \
|
||||||
$(srcdir)/database/updater/DatabaseFeatureExtractor.cpp \
|
$(srcdir)/database/updater/DatabaseFeatureExtractor.cpp \
|
||||||
$(srcdir)/database/updater/DatabaseHighLevelCluster.cpp \
|
$(srcdir)/database/updater/DatabaseHighLevelCluster.cpp \
|
||||||
@@ -45,14 +44,6 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/utils/Path.cpp \
|
$(srcdir)/utils/Path.cpp \
|
||||||
$(srcdir)/utils/Utils.cpp
|
$(srcdir)/utils/Utils.cpp
|
||||||
|
|
||||||
if VIDEO
|
|
||||||
lms_SOURCES += \
|
|
||||||
$(srcdir)/ui/video/VideoWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoDatabaseWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoMediaPlayerWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoParametersDialog.cpp
|
|
||||||
endif
|
|
||||||
|
|
||||||
lms_CXXFLAGS=-std=c++11 -Wall -I$(srcdir)/third-party -I$(srcdir)/ui $(MAGICKXX_CFLAGS) -D_REENTRANT -DBOOST_SPIRIT_THREADSAFE
|
lms_CXXFLAGS=-std=c++11 -Wall -I$(srcdir)/third-party -I$(srcdir)/ui $(MAGICKXX_CFLAGS) -D_REENTRANT -DBOOST_SPIRIT_THREADSAFE
|
||||||
lms_LDADD=$(MAGICKXX_LIBS)
|
lms_LDADD=$(MAGICKXX_LIBS)
|
||||||
|
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ Grabber::getFromRelease(Wt::Dbo::Session& session, Database::Release::id_type re
|
|||||||
|
|
||||||
Wt::Dbo::Transaction transaction(session);
|
Wt::Dbo::Transaction transaction(session);
|
||||||
|
|
||||||
// If the release does not exist or is the special release "None", do nothing
|
// If the release does not exist, do nothing
|
||||||
Release::pointer release = Release::getById(session, releaseId);
|
Release::pointer release = Release::getById(session, releaseId);
|
||||||
if (!release || release->isNone())
|
if (!release)
|
||||||
return std::vector<Image::Image>();
|
return std::vector<Image::Image>();
|
||||||
|
|
||||||
std::vector<Track::pointer> tracks = release->getTracks();
|
std::vector<Track::pointer> tracks = release->getTracks();
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Types.hpp"
|
|
||||||
#include "SqlQuery.hpp"
|
|
||||||
|
|
||||||
#include "utils/Logger.hpp"
|
|
||||||
|
|
||||||
namespace Database
|
|
||||||
{
|
|
||||||
|
|
||||||
Artist::Artist(const std::string& name, const std::string& MBID)
|
|
||||||
: _name(std::string(name, 0 , _maxNameLength)),
|
|
||||||
_MBID(MBID)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
|
||||||
Artist::getByName(Wt::Dbo::Session& session, const std::string& name)
|
|
||||||
{
|
|
||||||
Wt::Dbo::collection<Artist::pointer> res = session.find<Artist>().where("name = ?").bind( std::string(name, 0, _maxNameLength) );
|
|
||||||
return std::vector<Artist::pointer>(res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Artist::pointer
|
|
||||||
Artist::getByMBID(Wt::Dbo::Session& session, const std::string& mbid)
|
|
||||||
{
|
|
||||||
return session.find<Artist>().where("mbid = ?").bind(mbid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Artist::pointer
|
|
||||||
Artist::getById(Wt::Dbo::Session& session, Artist::id_type id)
|
|
||||||
{
|
|
||||||
return session.find<Artist>().where("id = ?").bind(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Artist::pointer
|
|
||||||
Artist::create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID)
|
|
||||||
{
|
|
||||||
return session.add(new Artist(name, MBID));
|
|
||||||
}
|
|
||||||
|
|
||||||
Artist::pointer
|
|
||||||
Artist::getNone(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
std::vector<pointer> res = getByName(session, "<None>");
|
|
||||||
if (res.empty())
|
|
||||||
return create(session, "<None>");
|
|
||||||
|
|
||||||
return res.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
|
||||||
Artist::getAll(Wt::Dbo::Session& session, int offset, int size)
|
|
||||||
{
|
|
||||||
Wt::Dbo::collection<pointer> res = session.find<Artist>().offset(offset).limit(size);
|
|
||||||
return std::vector<pointer>(res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
|
||||||
Artist::getAllOrphans(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
Wt::Dbo::collection<Artist::pointer> res = session.query< Wt::Dbo::ptr<Artist> >("select a from artist a LEFT OUTER JOIN Track t ON a.id = t.artist_id WHERE t.id IS NULL");
|
|
||||||
|
|
||||||
return std::vector<pointer>(res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
|
||||||
Artist::getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset, int size)
|
|
||||||
{
|
|
||||||
Wt::Dbo::collection<Artist::pointer> res = getQuery(session, filter).limit(size).offset(offset);
|
|
||||||
|
|
||||||
return std::vector<pointer>(res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
|
||||||
Artist::getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset, int size, bool& moreResults)
|
|
||||||
{
|
|
||||||
auto res = getByFilter(session, filter, offset, size + 1);
|
|
||||||
|
|
||||||
if (size != -1 && res.size() == static_cast<std::size_t>(size) + 1)
|
|
||||||
{
|
|
||||||
moreResults = true;
|
|
||||||
res.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
moreResults = false;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Wt::Dbo::ptr<Release> >
|
|
||||||
Artist::getReleases() const
|
|
||||||
{
|
|
||||||
assert(self());
|
|
||||||
assert(self()->id() != Wt::Dbo::dbo_traits<Artist>::invalidId() );
|
|
||||||
assert(session());
|
|
||||||
|
|
||||||
Wt::Dbo::collection< Wt::Dbo::ptr<Release> > res = session()->query<Wt::Dbo::ptr<Release> >("SELECT r FROM release r INNER JOIN artist a ON t.artist_id = a.id INNER JOIN track t ON t.release_id = r.id").where("a.id = ?").bind(id());
|
|
||||||
|
|
||||||
return std::vector< Wt::Dbo::ptr<Release> > (res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Wt::Dbo::Query<Artist::pointer>
|
|
||||||
Artist::getQuery(Wt::Dbo::Session& session, SearchFilter filter)
|
|
||||||
{
|
|
||||||
SqlQuery sqlQuery = generatePartialQuery(filter);
|
|
||||||
|
|
||||||
Wt::Dbo::Query<pointer> query
|
|
||||||
= session.query<pointer>( "SELECT a FROM artist a INNER JOIN track t ON t.artist_id = a.id INNER JOIN release r ON r.id = t.release_id INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id " + sqlQuery.where().get()).groupBy("a.id").orderBy("a.name");
|
|
||||||
|
|
||||||
for (const std::string& bindArg : sqlQuery.where().getBindArgs())
|
|
||||||
query.bind(bindArg);
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
Wt::Dbo::Query<Artist::UIQueryResult>
|
|
||||||
Artist::getUIQuery(Wt::Dbo::Session& session, SearchFilter filter)
|
|
||||||
{
|
|
||||||
SqlQuery sqlQuery = generatePartialQuery(filter);
|
|
||||||
|
|
||||||
Wt::Dbo::Query<UIQueryResult> query
|
|
||||||
= session.query<UIQueryResult>( "SELECT a.id, a.name, COUNT(DISTINCT r.id), COUNT(DISTINCT t.id) FROM artist a INNER JOIN track t ON t.artist_id = a.id INNER JOIN release r ON r.id = t.release_id INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id " + sqlQuery.where().get()).groupBy("a.id").orderBy("a.name");
|
|
||||||
|
|
||||||
for (const std::string& bindArg : sqlQuery.where().getBindArgs())
|
|
||||||
query.bind(bindArg);
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Artist::updateUIQueryModel(Wt::Dbo::Session& session, Wt::Dbo::QueryModel<UIQueryResult>& model, SearchFilter filter, const std::vector<Wt::WString>& columnNames)
|
|
||||||
{
|
|
||||||
Wt::Dbo::Query<UIQueryResult> query = getUIQuery(session, filter);
|
|
||||||
|
|
||||||
model.setQuery(query, columnNames.empty() ? true : false);
|
|
||||||
|
|
||||||
// TODO do something better
|
|
||||||
if (columnNames.size() == 3)
|
|
||||||
{
|
|
||||||
model.addColumn( "a.name", columnNames.at(0));
|
|
||||||
model.addColumn( "COUNT(DISTINCT r.id)", columnNames.at(1) );
|
|
||||||
model.addColumn( "COUNT(DISTINCT t.id)", columnNames.at(2) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Database
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DB_ARTIST_HPP_
|
|
||||||
#define _DB_ARTIST_HPP_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <Wt/Dbo/Dbo>
|
|
||||||
#include <Wt/Dbo/QueryModel>
|
|
||||||
|
|
||||||
#include "SearchFilter.hpp"
|
|
||||||
|
|
||||||
namespace Database
|
|
||||||
{
|
|
||||||
|
|
||||||
class Track;
|
|
||||||
class Cluster;
|
|
||||||
class Release;
|
|
||||||
|
|
||||||
class Artist : public Wt::Dbo::Dbo<Artist>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef Wt::Dbo::ptr<Artist> pointer;
|
|
||||||
typedef Wt::Dbo::dbo_traits<Artist>::IdType id_type;
|
|
||||||
|
|
||||||
Artist() {}
|
|
||||||
Artist(const std::string& name, const std::string& MBID = "");
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
|
||||||
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
|
||||||
static pointer getNone(Wt::Dbo::Session& session); // Special entry
|
|
||||||
static std::vector<pointer> getByName(Wt::Dbo::Session& session, const std::string& name);
|
|
||||||
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
|
|
||||||
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset, int size, bool& moreExpected);
|
|
||||||
|
|
||||||
static std::vector<pointer> getAll(Wt::Dbo::Session& session, int offset = -1, int size = -1);
|
|
||||||
static std::vector<pointer> getAllOrphans(Wt::Dbo::Session& session);
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
std::string getName(void) const { return _name; }
|
|
||||||
std::string getMBID(void) const { return _MBID; }
|
|
||||||
|
|
||||||
// Get the releases that have at least one track for this artist
|
|
||||||
std::vector<Wt::Dbo::ptr<Release> > getReleases() const;
|
|
||||||
|
|
||||||
void setMBID(std::string mbid) { _MBID = mbid; }
|
|
||||||
|
|
||||||
// Create
|
|
||||||
static pointer create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID = "");
|
|
||||||
|
|
||||||
// MVC models for the user interface
|
|
||||||
// ID, Artist name, albums, tracks
|
|
||||||
typedef boost::tuple<id_type, std::string, int, int> UIQueryResult;
|
|
||||||
static Wt::Dbo::Query<UIQueryResult> getUIQuery(Wt::Dbo::Session& session, SearchFilter filter);
|
|
||||||
static void updateUIQueryModel(Wt::Dbo::Session& session, Wt::Dbo::QueryModel<UIQueryResult>& model, SearchFilter filter, const std::vector<Wt::WString>& columnNames = std::vector<Wt::WString>());
|
|
||||||
|
|
||||||
bool isNone(void) const;
|
|
||||||
|
|
||||||
template<class Action>
|
|
||||||
void persist(Action& a)
|
|
||||||
{
|
|
||||||
Wt::Dbo::field(a, _name, "name");
|
|
||||||
Wt::Dbo::field(a, _MBID, "mbid");
|
|
||||||
|
|
||||||
Wt::Dbo::hasMany(a, _tracks, Wt::Dbo::ManyToOne, "artist");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static Wt::Dbo::Query<pointer> getQuery(Wt::Dbo::Session& session, SearchFilter filter);
|
|
||||||
|
|
||||||
static const std::size_t _maxNameLength = 128;
|
|
||||||
|
|
||||||
std::string _name;
|
|
||||||
std::string _MBID; // Musicbrainz Identifier
|
|
||||||
|
|
||||||
Wt::Dbo::collection< Wt::Dbo::ptr<Track> > _tracks; // Tracks of this artist
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Database
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -87,7 +87,6 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
|
|||||||
_session.mapClass<Database::Playlist>("playlist");
|
_session.mapClass<Database::Playlist>("playlist");
|
||||||
_session.mapClass<Database::PlaylistEntry>("playlist_entry");
|
_session.mapClass<Database::PlaylistEntry>("playlist_entry");
|
||||||
_session.mapClass<Database::Release>("release");
|
_session.mapClass<Database::Release>("release");
|
||||||
_session.mapClass<Database::Video>("video");
|
|
||||||
_session.mapClass<Database::MediaDirectory>("media_directory");
|
_session.mapClass<Database::MediaDirectory>("media_directory");
|
||||||
_session.mapClass<Database::Setting>("setting");
|
_session.mapClass<Database::Setting>("setting");
|
||||||
|
|
||||||
|
|||||||
@@ -57,22 +57,6 @@ Artist::create(Wt::Dbo::Session& session, const std::string& name, const std::st
|
|||||||
return session.add(new Artist(name, MBID));
|
return session.add(new Artist(name, MBID));
|
||||||
}
|
}
|
||||||
|
|
||||||
Artist::pointer
|
|
||||||
Artist::getNone(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
std::vector<pointer> res = getByName(session, "<None>");
|
|
||||||
if (res.empty())
|
|
||||||
return create(session, "<None>");
|
|
||||||
|
|
||||||
return res.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Artist::isNone() const
|
|
||||||
{
|
|
||||||
return _name == "<None>";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Artist::pointer>
|
std::vector<Artist::pointer>
|
||||||
Artist::getAll(Wt::Dbo::Session& session, int offset, int size)
|
Artist::getAll(Wt::Dbo::Session& session, int offset, int size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ class Artist : public Wt::Dbo::Dbo<Artist>
|
|||||||
// Accessors
|
// Accessors
|
||||||
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
||||||
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
||||||
static pointer getNone(Wt::Dbo::Session& session); // Special entry
|
|
||||||
static std::vector<pointer> getByName(Wt::Dbo::Session& session, const std::string& name);
|
static std::vector<pointer> getByName(Wt::Dbo::Session& session, const std::string& name);
|
||||||
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session,
|
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session,
|
||||||
const std::set<id_type>& clusters, // at least one track that belongs to these clusters
|
const std::set<id_type>& clusters, // at least one track that belongs to these clusters
|
||||||
@@ -72,7 +71,6 @@ class Artist : public Wt::Dbo::Dbo<Artist>
|
|||||||
// Create
|
// Create
|
||||||
static pointer create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID = "");
|
static pointer create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID = "");
|
||||||
|
|
||||||
bool isNone(void) const;
|
|
||||||
|
|
||||||
template<class Action>
|
template<class Action>
|
||||||
void persist(Action& a)
|
void persist(Action& a)
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ class MediaDirectory
|
|||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Audio = 1,
|
Audio = 1,
|
||||||
Video = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaDirectory() {}
|
MediaDirectory() {}
|
||||||
|
|||||||
@@ -56,22 +56,6 @@ Release::create(Wt::Dbo::Session& session, const std::string& name, const std::s
|
|||||||
return session.add(new Release(name, MBID));
|
return session.add(new Release(name, MBID));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Release::isNone() const
|
|
||||||
{
|
|
||||||
return _name == "<None>";
|
|
||||||
}
|
|
||||||
|
|
||||||
Release::pointer
|
|
||||||
Release::getNone(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
std::vector<pointer> res = getByName(session, "<None>");
|
|
||||||
if (res.empty())
|
|
||||||
return create(session, "<None>");
|
|
||||||
|
|
||||||
return res.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Release::pointer>
|
std::vector<Release::pointer>
|
||||||
Release::getAll(Wt::Dbo::Session& session, int offset, int size)
|
Release::getAll(Wt::Dbo::Session& session, int offset, int size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ class Release : public Wt::Dbo::Dbo<Release>
|
|||||||
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
||||||
static std::vector<pointer> getByName(Wt::Dbo::Session& session, const std::string& name);
|
static std::vector<pointer> getByName(Wt::Dbo::Session& session, const std::string& name);
|
||||||
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
||||||
static pointer getNone(Wt::Dbo::Session& session); // Special entry
|
|
||||||
static std::vector<pointer> getAllOrphans(Wt::Dbo::Session& session); // no track related
|
static std::vector<pointer> getAllOrphans(Wt::Dbo::Session& session); // no track related
|
||||||
static std::vector<pointer> getAll(Wt::Dbo::Session& session, int offset, int size);
|
static std::vector<pointer> getAll(Wt::Dbo::Session& session, int offset, int size);
|
||||||
|
|
||||||
@@ -68,7 +67,6 @@ class Release : public Wt::Dbo::Dbo<Release>
|
|||||||
// Accessors
|
// Accessors
|
||||||
std::string getName() const { return _name; }
|
std::string getName() const { return _name; }
|
||||||
std::string getMBID() const { return _MBID; }
|
std::string getMBID() const { return _MBID; }
|
||||||
bool isNone(void) const;
|
|
||||||
boost::posix_time::time_duration getDuration(void) const;
|
boost::posix_time::time_duration getDuration(void) const;
|
||||||
|
|
||||||
// Get the artists of this release
|
// Get the artists of this release
|
||||||
|
|||||||
@@ -240,21 +240,6 @@ Cluster::getByType(Wt::Dbo::Session& session, std::string type)
|
|||||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
Cluster::pointer
|
|
||||||
Cluster::getNone(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
pointer res = get(session, "<None>", "<None>");
|
|
||||||
if (!res)
|
|
||||||
res = create(session, "<None>", "<None>");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Cluster::isNone(void) const
|
|
||||||
{
|
|
||||||
return (_type == "<None>" && _name == "<None>");
|
|
||||||
}
|
|
||||||
|
|
||||||
Cluster::pointer
|
Cluster::pointer
|
||||||
Cluster::create(Wt::Dbo::Session& session, std::string type, std::string name)
|
Cluster::create(Wt::Dbo::Session& session, std::string type, std::string name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class Cluster
|
|||||||
|
|
||||||
// Find utility
|
// Find utility
|
||||||
static pointer get(Wt::Dbo::Session& session, std::string type, std::string name);
|
static pointer get(Wt::Dbo::Session& session, std::string type, std::string name);
|
||||||
static pointer getNone(Wt::Dbo::Session& session);
|
|
||||||
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
|
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
|
||||||
static Wt::Dbo::collection<pointer> getAll(Wt::Dbo::Session& session);
|
static Wt::Dbo::collection<pointer> getAll(Wt::Dbo::Session& session);
|
||||||
static std::vector<std::string> getAllTypes(Wt::Dbo::Session& session);
|
static std::vector<std::string> getAllTypes(Wt::Dbo::Session& session);
|
||||||
@@ -74,7 +73,6 @@ class Cluster
|
|||||||
// Accessors
|
// Accessors
|
||||||
const std::string& getName(void) const { return _name; }
|
const std::string& getName(void) const { return _name; }
|
||||||
const std::string& getType(void) const { return _type; }
|
const std::string& getType(void) const { return _type; }
|
||||||
bool isNone(void) const;
|
|
||||||
const Wt::Dbo::collection< Wt::Dbo::ptr<Track> >& getTracks() const { return _tracks;}
|
const Wt::Dbo::collection< Wt::Dbo::ptr<Track> >& getTracks() const { return _tracks;}
|
||||||
|
|
||||||
void addTrack(Wt::Dbo::Session& session, Wt::Dbo::dbo_traits<Track>::IdType trackId);
|
void addTrack(Wt::Dbo::Session& session, Wt::Dbo::dbo_traits<Track>::IdType trackId);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "Track.hpp"
|
#include "Track.hpp"
|
||||||
#include "Playlist.hpp"
|
#include "Playlist.hpp"
|
||||||
#include "Release.hpp"
|
#include "Release.hpp"
|
||||||
#include "Video.hpp"
|
|
||||||
#include "MediaDirectory.hpp"
|
#include "MediaDirectory.hpp"
|
||||||
#include "User.hpp"
|
#include "User.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Types.hpp"
|
|
||||||
|
|
||||||
namespace Database {
|
|
||||||
|
|
||||||
Video::Video()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Video::Video(const boost::filesystem::path& p)
|
|
||||||
: _filePath(p.string())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Video::pointer
|
|
||||||
Video::create(Wt::Dbo::Session& session, const boost::filesystem::path& p)
|
|
||||||
{
|
|
||||||
return session.add(new Video(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
Wt::Dbo::collection< Video::pointer >
|
|
||||||
Video::getAll(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
return session.find<Video>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Video::pointer
|
|
||||||
Video::getByPath(Wt::Dbo::Session& session, const boost::filesystem::path& p)
|
|
||||||
{
|
|
||||||
return session.find<Video>().where("path = ?").bind(p.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<boost::filesystem::path>
|
|
||||||
Video::getAllPaths(Wt::Dbo::Session& session)
|
|
||||||
{
|
|
||||||
Wt::Dbo::Transaction transaction(session);
|
|
||||||
Wt::Dbo::collection<std::string> res = session.query<std::string>("SELECT path from video");
|
|
||||||
return std::vector<boost::filesystem::path>(res.begin(), res.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Video
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _VIDEO_TYPES_HPP
|
|
||||||
#define _VIDEO_TYPES_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <Wt/Dbo/Dbo>
|
|
||||||
#include <Wt/Dbo/WtSqlTraits>
|
|
||||||
|
|
||||||
#include <Wt/WDateTime>
|
|
||||||
|
|
||||||
namespace Database {
|
|
||||||
|
|
||||||
class Video
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef Wt::Dbo::ptr<Video> pointer;
|
|
||||||
|
|
||||||
Video();
|
|
||||||
Video( const boost::filesystem::path& p);
|
|
||||||
|
|
||||||
// Find utilities
|
|
||||||
static pointer getByPath(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
|
||||||
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
|
|
||||||
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session);
|
|
||||||
|
|
||||||
// Create utility
|
|
||||||
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
|
||||||
|
|
||||||
// Modifiers
|
|
||||||
void setName(const std::string& name) { _name = name; }
|
|
||||||
void setDuration(boost::posix_time::time_duration duration) { _duration = duration; }
|
|
||||||
void setLastWriteTime(boost::posix_time::ptime time) { _fileLastWrite = time; }
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
std::string getName(void) const { return _name; }
|
|
||||||
boost::posix_time::time_duration getDuration(void) const { return _duration; }
|
|
||||||
boost::filesystem::path getPath(void) const { return _filePath; }
|
|
||||||
boost::posix_time::ptime getLastWriteTime(void) const { return _fileLastWrite; }
|
|
||||||
|
|
||||||
template<class Action>
|
|
||||||
void persist(Action& a)
|
|
||||||
{
|
|
||||||
Wt::Dbo::field(a, _name, "name");
|
|
||||||
Wt::Dbo::field(a, _duration, "duration");
|
|
||||||
Wt::Dbo::field(a, _fileLastWrite, "last_write");
|
|
||||||
Wt::Dbo::field(a, _filePath, "path");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::string _name;
|
|
||||||
boost::posix_time::time_duration _duration;
|
|
||||||
std::string _filePath;
|
|
||||||
boost::posix_time::ptime _fileLastWrite;
|
|
||||||
|
|
||||||
}; // Video
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Database
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -240,7 +240,6 @@ Updater::process(boost::system::error_code err)
|
|||||||
Stats stats;
|
Stats stats;
|
||||||
|
|
||||||
checkAudioFiles(stats);
|
checkAudioFiles(stats);
|
||||||
checkVideoFiles(stats);
|
|
||||||
|
|
||||||
std::vector<RootDirectory> rootDirectories;
|
std::vector<RootDirectory> rootDirectories;
|
||||||
{
|
{
|
||||||
@@ -296,10 +295,6 @@ Updater::updateFileExtensions()
|
|||||||
_audioFileExtensions.clear();
|
_audioFileExtensions.clear();
|
||||||
for (auto extension : splitString(Setting::getString(_db->getSession(), "audio_file_extensions"), " "))
|
for (auto extension : splitString(Setting::getString(_db->getSession(), "audio_file_extensions"), " "))
|
||||||
_audioFileExtensions.push_back( extension );
|
_audioFileExtensions.push_back( extension );
|
||||||
|
|
||||||
_videoFileExtensions.clear();
|
|
||||||
for (auto extension : splitString(Setting::getString(_db->getSession(), "video_file_extensions"), " "))
|
|
||||||
_videoFileExtensions.push_back( extension );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Artist::pointer
|
Artist::pointer
|
||||||
@@ -336,7 +331,7 @@ Updater::getArtist( const boost::filesystem::path& file, const std::string& name
|
|||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Artist::getNone( _db->getSession() );
|
return Artist::pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Release::pointer
|
Release::pointer
|
||||||
@@ -373,7 +368,7 @@ Updater::getRelease( const boost::filesystem::path& file, const std::string& nam
|
|||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Release::getNone( _db->getSession() );
|
return Release::pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Cluster::pointer>
|
std::vector<Cluster::pointer>
|
||||||
@@ -390,9 +385,6 @@ Updater::getGenreClusters( const std::list<std::string>& names)
|
|||||||
genres.push_back( genre );
|
genres.push_back( genre );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (genres.empty())
|
|
||||||
genres.push_back( Cluster::getNone( _db->getSession() ));
|
|
||||||
|
|
||||||
return genres;
|
return genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +478,6 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
|
|||||||
// TODO rename
|
// TODO rename
|
||||||
genres = getGenreClusters( genreList );
|
genres = getGenreClusters( genreList );
|
||||||
}
|
}
|
||||||
assert( !genres.empty() );
|
|
||||||
|
|
||||||
// ***** Artist
|
// ***** Artist
|
||||||
Artist::pointer artist;
|
Artist::pointer artist;
|
||||||
@@ -502,7 +493,6 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
|
|||||||
|
|
||||||
artist = getArtist(file, artistName, artistMusicBrainzID);
|
artist = getArtist(file, artistName, artistMusicBrainzID);
|
||||||
}
|
}
|
||||||
assert(artist);
|
|
||||||
|
|
||||||
// ***** Release
|
// ***** Release
|
||||||
Release::pointer release;
|
Release::pointer release;
|
||||||
@@ -543,8 +533,10 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
|
|||||||
assert(track);
|
assert(track);
|
||||||
|
|
||||||
track.modify()->setChecksum(checksum);
|
track.modify()->setChecksum(checksum);
|
||||||
track.modify()->setArtist(artist);
|
if (artist)
|
||||||
track.modify()->setRelease(release);
|
track.modify()->setArtist(artist);
|
||||||
|
if (release)
|
||||||
|
track.modify()->setRelease(release);
|
||||||
track.modify()->setLastWriteTime(lastWriteTime);
|
track.modify()->setLastWriteTime(lastWriteTime);
|
||||||
track.modify()->setName(title);
|
track.modify()->setName(title);
|
||||||
track.modify()->setDuration( boost::any_cast<boost::posix_time::time_duration>(items[MetaData::Type::Duration]) );
|
track.modify()->setDuration( boost::any_cast<boost::posix_time::time_duration>(items[MetaData::Type::Duration]) );
|
||||||
@@ -631,11 +623,6 @@ Updater::processRootDirectory(RootDirectory rootDirectory, Stats& stats)
|
|||||||
processAudioFile(path, stats );
|
processAudioFile(path, stats );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Database::MediaDirectory::Video:
|
|
||||||
if (isFileSupported(path, _videoFileExtensions))
|
|
||||||
processVideoFile(path, stats);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -785,101 +772,5 @@ Updater::checkDuplicatedAudioFiles(Stats& stats)
|
|||||||
LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files done!";
|
LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files done!";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Updater::checkVideoFiles( Stats& stats )
|
|
||||||
{
|
|
||||||
std::vector<boost::filesystem::path> rootDirs = getRootDirectoriesByType(_db->getSession(), Database::MediaDirectory::Video);
|
|
||||||
std::vector<boost::filesystem::path> videoPaths = Video::getAllPaths(_db->getSession());
|
|
||||||
|
|
||||||
LMS_LOG(DBUPDATER, DEBUG) << "Checking videos...";
|
|
||||||
for (auto& videoPath : videoPaths)
|
|
||||||
{
|
|
||||||
if (!_running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!checkFile(videoPath, rootDirs, _videoFileExtensions))
|
|
||||||
{
|
|
||||||
Wt::Dbo::Transaction transaction(_db->getSession());
|
|
||||||
|
|
||||||
Video::pointer video = Video::getByPath(_db->getSession(), videoPath);
|
|
||||||
if (video)
|
|
||||||
{
|
|
||||||
video.remove();
|
|
||||||
stats.nbRemoved++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LMS_LOG(DBUPDATER, DEBUG) << "Check video files done!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Updater::processVideoFile( const boost::filesystem::path& file, Stats& stats)
|
|
||||||
{
|
|
||||||
// Check last update time
|
|
||||||
boost::posix_time::ptime lastWriteTime (boost::posix_time::from_time_t( boost::filesystem::last_write_time( file ) ) );
|
|
||||||
|
|
||||||
Wt::Dbo::Transaction transaction(_db->getSession());
|
|
||||||
|
|
||||||
// Skip file if last write is the same
|
|
||||||
Wt::Dbo::ptr<Video> video = Video::getByPath(_db->getSession(), file);
|
|
||||||
if (video && video->getLastWriteTime() == lastWriteTime)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MetaData::Items items;
|
|
||||||
if (!_metadataParser.parse(file, items))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// We estimate this is a video if:
|
|
||||||
// - we found a least one video stream
|
|
||||||
// - the duration is not null
|
|
||||||
if (items.find(MetaData::Type::VideoStreams) == items.end()
|
|
||||||
|| boost::any_cast<std::vector<MetaData::VideoStream> >(items[MetaData::Type::VideoStreams]).empty())
|
|
||||||
{
|
|
||||||
LMS_LOG(DBUPDATER, ERROR) << "Skipped '" << file << "' (no video stream found)";
|
|
||||||
|
|
||||||
// If the video exists here, delete it!
|
|
||||||
if (video) {
|
|
||||||
video.remove();
|
|
||||||
stats.nbRemoved++;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (items.find(MetaData::Type::Duration) == items.end()
|
|
||||||
|| boost::any_cast<boost::posix_time::time_duration>(items[MetaData::Type::Duration]).total_seconds() == 0)
|
|
||||||
{
|
|
||||||
LMS_LOG(DBUPDATER, ERROR) << "Skipped '" << file << "' (no duration or duration 0)";
|
|
||||||
|
|
||||||
// If Track exists here, delete it!
|
|
||||||
if (video) {
|
|
||||||
video.remove();
|
|
||||||
stats.nbRemoved++;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If video already exist, update data
|
|
||||||
// Otherwise, create it
|
|
||||||
// Today we are very aggressive, but we could also guess names from path, etc.
|
|
||||||
if (!video)
|
|
||||||
{
|
|
||||||
video = Video::create(_db->getSession(), file);
|
|
||||||
LMS_LOG(DBUPDATER, DEBUG) << "Adding '" << file << "'";
|
|
||||||
stats.nbAdded++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LMS_LOG(DBUPDATER, DEBUG) << "Updating '" << file << "'";
|
|
||||||
stats.nbUpdated++;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(video);
|
|
||||||
|
|
||||||
video.modify()->setName( file.filename().string() );
|
|
||||||
video.modify()->setDuration( boost::any_cast<boost::posix_time::time_duration>(items[MetaData::Type::Duration]) );
|
|
||||||
video.modify()->setLastWriteTime(lastWriteTime);
|
|
||||||
|
|
||||||
transaction.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -81,9 +81,6 @@ Artist::refresh()
|
|||||||
auto releases = artist->getReleases(_filters->getClusterIds());
|
auto releases = artist->getReleases(_filters->getClusterIds());
|
||||||
for (auto release : releases)
|
for (auto release : releases)
|
||||||
{
|
{
|
||||||
if (release->isNone())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-artist-entry"), releasesContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-artist-entry"), releasesContainer);
|
||||||
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ Release::refresh()
|
|||||||
|
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
||||||
|
|
||||||
if (variousArtists && !track->getArtist()->isNone())
|
if (variousArtists && track->getArtist())
|
||||||
{
|
{
|
||||||
entry->setCondition("if-has-artist", true);
|
entry->setCondition("if-has-artist", true);
|
||||||
Wt::WAnchor *artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(track->getArtist().id())));
|
Wt::WAnchor *artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(track->getArtist().id())));
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ Tracks::refresh(std::vector<std::string> searchKeywords)
|
|||||||
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
||||||
|
|
||||||
auto artist = track->getArtist();
|
auto artist = track->getArtist();
|
||||||
if (!artist->isNone())
|
if (artist)
|
||||||
{
|
{
|
||||||
entry->setCondition("if-has-artist", true);
|
entry->setCondition("if-has-artist", true);
|
||||||
Wt::WAnchor *artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(track->getArtist().id())));
|
Wt::WAnchor *artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(track->getArtist().id())));
|
||||||
@@ -91,7 +91,7 @@ Tracks::refresh(std::vector<std::string> searchKeywords)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto release = track->getRelease();
|
auto release = track->getRelease();
|
||||||
if (!release->isNone())
|
if (release)
|
||||||
{
|
{
|
||||||
entry->setCondition("if-has-release", true);
|
entry->setCondition("if-has-release", true);
|
||||||
// TODO anchor
|
// TODO anchor
|
||||||
|
|||||||
Reference in New Issue
Block a user