MythTV master
playlistcontainer.cpp
Go to the documentation of this file.
1// C/C++
2#include <utility>
3
4// MythTV
9
10// mythmusic
11#include "playlist.h"
12#include "playlistcontainer.h"
13
15{
16 RunProlog();
17 while (!m_allMusic->doneLoading())
18 {
19 usleep(250ms); // cppcheck-suppress usleepCalled
20 }
21 m_parent->load();
22 RunEpilog();
23}
24
25#define LOC QString("PlaylistContainer: ")
26#define LOC_WARN QString("PlaylistContainer, Warning: ")
27#define LOC_ERR QString("PlaylistContainer, Error: ")
28
30 m_playlistsLoader(new PlaylistLoadingThread(this, all_music)),
31 m_myHost(gCoreContext->GetHostName()),
32
33 m_ratingWeight( gCoreContext->GetNumSetting("IntelliRatingWeight", 2)),
34 m_playCountWeight(gCoreContext->GetNumSetting("IntelliPlayCountWeight", 2)),
35 m_lastPlayWeight( gCoreContext->GetNumSetting("IntelliLastPlayWeight", 2)),
36 m_randomWeight( gCoreContext->GetNumSetting("IntelliRandomWeight", 2))
37{
39}
40
42{
44 delete m_playlistsLoader;
45 m_playlistsLoader = nullptr;
46
47 delete m_activePlaylist;
48 delete m_streamPlaylist;
50 {
51 while (!m_allPlaylists->empty())
52 {
53 delete m_allPlaylists->front();
54 m_allPlaylists->pop_front();
55 }
56 delete m_allPlaylists;
57 }
58}
59
61 int &lastplay, int &random) const
62{
64 playcount = m_playCountWeight;
65 lastplay = m_lastPlayWeight;
66 random = m_randomWeight;
67}
68
70{
71 m_doneLoading = false;
74
77
78 m_allPlaylists = new QList<Playlist*>;
79
81
83
85 query.prepare("SELECT playlist_id FROM music_playlists "
86 "WHERE playlist_name != :DEFAULT"
87 " AND playlist_name != :BACKUP "
88 " AND playlist_name != :STREAM "
89 " AND (hostname = '' OR hostname = :HOST) "
90 "ORDER BY playlist_name;");
91 query.bindValue(":DEFAULT", DEFAULT_PLAYLIST_NAME);
92 query.bindValue(":BACKUP", "backup_playlist_storage");
93 query.bindValue(":STREAM", DEFAULT_STREAMLIST_NAME);
94 query.bindValue(":HOST", m_myHost);
95
96 if (!query.exec())
97 {
98 MythDB::DBError("Querying playlists", query);
99 }
100 else
101 {
102 while (query.next())
103 {
104 auto *temp_playlist = new Playlist();
105 // No, we don't destruct this ...
106 temp_playlist->setParent(this);
107 temp_playlist->loadPlaylistByID(query.value(0).toInt(), m_myHost);
108 m_allPlaylists->push_back(temp_playlist);
109 // ... cause it's sitting on this PtrList
110 }
111 }
112
113 m_doneLoading = true;
114}
115
116// resync all the playlists after a rescan just in case some tracks were removed
118{
119 // NOLINTNEXTLINE(modernize-loop-convert)
120 for (auto it = m_allPlaylists->begin(); it != m_allPlaylists->end(); ++it)
121 (*it)->resync();
122
124}
125
127{
128 // Debugging
130 for (const auto & playlist : std::as_const(*m_allPlaylists))
131 playlist->describeYourself();
132}
133
135{
136 // return a pointer to a playlist
137 // by id;
138
139 if (m_activePlaylist->getID() == id)
140 {
141 return m_activePlaylist;
142 }
143
144 auto idmatch = [id](const auto & playlist)
145 { return playlist->getID() == id; };
146 auto it = std::find_if(m_allPlaylists->cbegin(), m_allPlaylists->cend(), idmatch);
147 if (it != m_allPlaylists->cend())
148 return *it;
149
150 LOG(VB_GENERAL, LOG_ERR,
151 "getPlaylistName() called with unknown index number");
152 return nullptr;
153}
154
156{
157 // return a pointer to a playlist
158 // by name;
159 auto namematch = [name](const auto & playlist)
160 { return playlist->getName() == name; };
161 auto it = std::find_if(m_allPlaylists->cbegin(), m_allPlaylists->cend(), namematch);
162 if (it != m_allPlaylists->cend())
163 return *it;
164
165 LOG(VB_GENERAL, LOG_ERR, QString("getPlaylistName() called with unknown name: %1").arg(name));
166 return nullptr;
167}
168
170{
171 // NOLINTNEXTLINE(modernize-loop-convert)
172 for (auto it = m_allPlaylists->begin(); it != m_allPlaylists->end(); ++it)
173 {
174 if ((*it)->hasChanged())
175 (*it)->savePlaylist((*it)->getName(), m_myHost);
176 }
177
180}
181
183{
184 auto *new_list = new Playlist();
185 new_list->setParent(this);
186
187 // Need to touch the database to get persistent ID
188 new_list->savePlaylist(name, m_myHost);
189
190 m_allPlaylists->push_back(new_list);
191}
192
193void PlaylistContainer::copyNewPlaylist(const QString &name)
194{
195 auto *new_list = new Playlist();
196 new_list->setParent(this);
197
198 // Need to touch the database to get persistent ID
199 new_list->savePlaylist(name, m_myHost);
200
201 m_allPlaylists->push_back(new_list);
202 m_activePlaylist->copyTracks(new_list, false);
203}
204
206{
208 Playlist *copy_from = getPlaylist(index);
209 if (!copy_from)
210 {
211 LOG(VB_GENERAL, LOG_ERR, LOC + "copyToActive() " +
212 QString("Unknown playlist: %1").arg(index));
213 return;
214 }
215 copy_from->copyTracks(m_activePlaylist, true);
216}
217
218void PlaylistContainer::renamePlaylist(int index, const QString& new_name)
219{
220 Playlist *list_to_rename = getPlaylist(index);
221 if (list_to_rename)
222 {
223 list_to_rename->setName(new_name);
224 list_to_rename->changed();
225 }
226}
227
229{
230 Playlist *list_to_kill = getPlaylist(kill_me);
231 if (!list_to_kill)
232 {
233 LOG(VB_GENERAL, LOG_ERR, LOC + "deletePlaylist() " +
234 QString("Unknown playlist: %1").arg(kill_me));
235 return;
236 }
237
238 list_to_kill->removeAllTracks();
239 m_allPlaylists->removeAll(list_to_kill);
240
242 query.prepare("DELETE FROM music_playlists WHERE playlist_id = :ID ;");
243 query.bindValue(":ID", kill_me);
244
245 if (!query.exec() || query.numRowsAffected() < 1)
246 {
247 MythDB::DBError("playlist delete", query);
248 }
249}
250
251
252QString PlaylistContainer::getPlaylistName(int index, bool &reference)
253{
255 {
256 if (m_activePlaylist->getID() == index)
257 {
258 return m_activePlaylist->getName();
259 }
260
261 auto indexmatch = [index](const auto & playlist)
262 { return playlist->getID() == index; };
263 auto it = std::find_if(m_allPlaylists->cbegin(), m_allPlaylists->cend(), indexmatch);
264 if (it != m_allPlaylists->cend())
265 return (*it)->getName();
266 }
267
268 LOG(VB_GENERAL, LOG_ERR, LOC +
269 "getPlaylistName() called with unknown index number");
270
271 reference = true;
272 return tr("Something is Wrong");
273}
274
275bool PlaylistContainer::nameIsUnique(const QString& a_name, int which_id)
276{
277 if (a_name == DEFAULT_PLAYLIST_NAME)
278 return false;
279
280 auto itemfound = [a_name,which_id](const auto & playlist)
281 { return playlist->getName() == a_name &&
282 playlist->getID() != which_id; };
283 return std::none_of(m_allPlaylists->cbegin(), m_allPlaylists->cend(), itemfound);
284}
285
287{
288 QStringList res;
289
290 for (const auto & playlist : std::as_const(*m_allPlaylists))
291 {
292 res.append(playlist->getName());
293 }
294
295 return res;
296}
297
299{
301 {
302 return true;
303 }
305 return false;
306}
307
309{
311}
bool doneLoading() const
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
QVariant value(int i) const
Definition: mythdbcon.h:204
int numRowsAffected() const
Definition: mythdbcon.h:217
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
bool isFinished(void) const
Definition: mthread.cpp:258
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
void describeYourself(void) const
Playlist * getPlaylist(int id)
PlaylistLoadingThread * m_playlistsLoader
void renamePlaylist(int index, const QString &new_name)
PlaylistContainer(AllMusic *all_music)
void FillIntelliWeights(int &rating, int &playcount, int &lastplay, int &random) const
void copyToActive(int index)
void createNewPlaylist(const QString &name)
QString getPlaylistName(int index, bool &reference)
bool nameIsUnique(const QString &a_name, int which_id)
void deletePlaylist(int kill_me)
Playlist * m_streamPlaylist
QList< Playlist * > * m_allPlaylists
void copyNewPlaylist(const QString &name)
Playlist * m_activePlaylist
QStringList getPlaylistNames(void)
PlaylistContainer * m_parent
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
int getID(void) const
Definition: playlist.h:111
void setName(const QString &a_name)
Definition: playlist.h:107
QString getName(void)
Definition: playlist.h:106
void copyTracks(Playlist *to_ptr, bool update_display)
Definition: playlist.cpp:43
void resync(void)
make sure all tracks are still valid after a scan
Definition: playlist.cpp:613
void describeYourself(void) const
Definition: playlist.cpp:481
void removeAllTracks(void)
Definition: playlist.cpp:89
void changed(void)
Definition: playlist.cpp:990
void setParent(PlaylistContainer *myparent)
Definition: playlist.h:53
void savePlaylist(const QString &a_name, const QString &a_host)
Definition: playlist.cpp:998
void loadPlaylist(const QString &a_name, const QString &a_host)
Definition: playlist.cpp:529
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
def rating(profile, smoonURL, gate)
Definition: scan.py:36
#define LOC
static constexpr const char * DEFAULT_STREAMLIST_NAME
static constexpr const char * DEFAULT_PLAYLIST_NAME