MythTV  master
playlistcontainer.cpp
Go to the documentation of this file.
1 // MythTV
2 #include <mythcontext.h>
3 #include <mythdb.h>
4 #include <compat.h>
5 #include <mythlogging.h>
6 
7 #include <utility>
8 
9 // mythmusic
10 #include "playlist.h"
11 #include "playlistcontainer.h"
12 
13 
15 {
16  RunProlog();
17  while (!m_allMusic->doneLoading())
18  {
19  msleep(250);
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;
49  if (m_allPlaylists)
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;
67 }
68 
70 {
71  m_doneLoading = false;
72  m_activePlaylist = new Playlist();
74 
75  m_streamPlaylist = new Playlist();
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;");
92  query.bindValue(":BACKUP", "backup_playlist_storage");
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 : qAsConst(*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  for (const auto & playlist : qAsConst(*m_allPlaylists))
145  {
146  if (playlist->getID() == id)
147  return playlist;
148  }
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 
160  for (const auto & playlist : qAsConst(*m_allPlaylists))
161  {
162  if (playlist->getName() == name)
163  return playlist;
164  }
165 
166  LOG(VB_GENERAL, LOG_ERR, QString("getPlaylistName() called with unknown name: %1").arg(name));
167  return nullptr;
168 }
169 
171 {
172  // NOLINTNEXTLINE(modernize-loop-convert)
173  for (auto it = m_allPlaylists->begin(); it != m_allPlaylists->end(); ++it)
174  {
175  if ((*it)->hasChanged())
176  (*it)->savePlaylist((*it)->getName(), m_myHost);
177  }
178 
181 }
182 
183 void PlaylistContainer::createNewPlaylist(const QString &name)
184 {
185  auto *new_list = new Playlist();
186  new_list->setParent(this);
187 
188  // Need to touch the database to get persistent ID
189  new_list->savePlaylist(name, m_myHost);
190 
191  m_allPlaylists->push_back(new_list);
192 }
193 
194 void PlaylistContainer::copyNewPlaylist(const QString &name)
195 {
196  auto *new_list = new Playlist();
197  new_list->setParent(this);
198 
199  // Need to touch the database to get persistent ID
200  new_list->savePlaylist(name, m_myHost);
201 
202  m_allPlaylists->push_back(new_list);
203  m_activePlaylist->copyTracks(new_list, false);
204 }
205 
207 {
209  Playlist *copy_from = getPlaylist(index);
210  if (!copy_from)
211  {
212  LOG(VB_GENERAL, LOG_ERR, LOC + "copyToActive() " +
213  QString("Unknown playlist: %1").arg(index));
214  return;
215  }
216  copy_from->copyTracks(m_activePlaylist, true);
217 }
218 
219 void PlaylistContainer::renamePlaylist(int index, QString new_name)
220 {
221  Playlist *list_to_rename = getPlaylist(index);
222  if (list_to_rename)
223  {
224  list_to_rename->setName(std::move(new_name));
225  list_to_rename->changed();
226  }
227 }
228 
230 {
231  Playlist *list_to_kill = getPlaylist(kill_me);
232  if (!list_to_kill)
233  {
234  LOG(VB_GENERAL, LOG_ERR, LOC + "deletePlaylist() " +
235  QString("Unknown playlist: %1").arg(kill_me));
236  return;
237  }
238 
239  list_to_kill->removeAllTracks();
240  m_allPlaylists->removeAll(list_to_kill);
241 
243  query.prepare("DELETE FROM music_playlists WHERE playlist_id = :ID ;");
244  query.bindValue(":ID", kill_me);
245 
246  if (!query.exec() || query.numRowsAffected() < 1)
247  {
248  MythDB::DBError("playlist delete", query);
249  }
250 }
251 
252 
253 QString PlaylistContainer::getPlaylistName(int index, bool &reference)
254 {
255  if (m_activePlaylist)
256  {
257  if (m_activePlaylist->getID() == index)
258  {
259  return m_activePlaylist->getName();
260  }
261 
262  for (const auto & playlist : qAsConst(*m_allPlaylists))
263  {
264  if (playlist->getID() == index)
265  return playlist->getName();
266  }
267  }
268 
269  LOG(VB_GENERAL, LOG_ERR, LOC +
270  "getPlaylistName() called with unknown index number");
271 
272  reference = true;
273  return tr("Something is Wrong");
274 }
275 
276 bool PlaylistContainer::nameIsUnique(const QString& a_name, int which_id)
277 {
278  if (a_name == DEFAULT_PLAYLIST_NAME)
279  return false;
280 
281  for (const auto & playlist : qAsConst(*m_allPlaylists))
282  {
283  if (playlist->getName() == a_name && playlist->getID() != which_id)
284  return false;
285  }
286 
287  return true;
288 }
289 
291 {
292  QStringList res;
293 
294  for (const auto & playlist : qAsConst(*m_allPlaylists))
295  {
296  res.append(playlist->getName());
297  }
298 
299  return res;
300 }
301 
303 {
305  {
306  return true;
307  }
309  return false;
310 }
311 
313 {
315 }
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
PlaylistContainer::~PlaylistContainer
~PlaylistContainer()
Definition: playlistcontainer.cpp:41
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
MThread::msleep
static void msleep(unsigned long time)
Definition: mthread.cpp:341
playlistcontainer.h
DEFAULT_PLAYLIST_NAME
#define DEFAULT_PLAYLIST_NAME
Definition: playlistcontainer.h:11
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:292
PlaylistContainer::m_playCountWeight
int m_playCountWeight
Definition: playlistcontainer.h:84
PlaylistContainer::getPlaylistName
QString getPlaylistName(int index, bool &reference)
Definition: playlistcontainer.cpp:253
mythdb.h
AllMusic
Definition: musicmetadata.h:417
Playlist::setParent
void setParent(PlaylistContainer *myparent)
Definition: playlist.h:53
PlaylistContainer::PlaylistContainer
PlaylistContainer(AllMusic *all_music)
Definition: playlistcontainer.cpp:29
PlaylistLoadingThread::m_parent
PlaylistContainer * m_parent
Definition: playlistcontainer.h:29
PlaylistContainer::createNewPlaylist
void createNewPlaylist(const QString &name)
Definition: playlistcontainer.cpp:183
Playlist
Definition: playlist.h:45
Playlist::getName
QString getName(void)
Definition: playlist.h:106
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
PlaylistContainer::deletePlaylist
void deletePlaylist(int kill_me)
Definition: playlistcontainer.cpp:229
PlaylistContainer::copyNewPlaylist
void copyNewPlaylist(const QString &name)
Definition: playlistcontainer.cpp:194
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:202
PlaylistContainer::describeYourself
void describeYourself(void) const
Definition: playlistcontainer.cpp:126
PlaylistContainer::getPlaylistNames
QStringList getPlaylistNames(void)
Definition: playlistcontainer.cpp:290
PlaylistLoadingThread
Definition: playlistcontainer.h:18
PlaylistContainer::FillIntelliWeights
void FillIntelliWeights(int &rating, int &playcount, int &lastplay, int &random) const
Definition: playlistcontainer.cpp:60
mythlogging.h
AllMusic::doneLoading
bool doneLoading() const
Definition: musicmetadata.h:443
Playlist::setName
void setName(QString a_name)
Definition: playlist.h:107
Playlist::changed
void changed(void)
Definition: playlist.cpp:988
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
compat.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
hardwareprofile.scan.rating
def rating(profile, smoonURL, gate)
Definition: scan.py:39
PlaylistContainer::m_streamPlaylist
Playlist * m_streamPlaylist
Definition: playlistcontainer.h:76
Playlist::resync
void resync(void)
make sure all tracks are still valid after a scan
Definition: playlist.cpp:607
PlaylistContainer::getPlaylist
Playlist * getPlaylist(int id)
Definition: playlistcontainer.cpp:134
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:215
PlaylistContainer::nameIsUnique
bool nameIsUnique(const QString &a_name, int which_id)
Definition: playlistcontainer.cpp:276
MThread::isFinished
bool isFinished(void) const
Definition: mthread.cpp:267
PlaylistContainer::resync
void resync(void)
Definition: playlistcontainer.cpp:117
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
PlaylistContainer::m_playlistsLoader
PlaylistLoadingThread * m_playlistsLoader
Definition: playlistcontainer.h:79
Playlist::loadPlaylist
void loadPlaylist(const QString &a_name, const QString &a_host)
Definition: playlist.cpp:522
PlaylistContainer::load
void load()
Definition: playlistcontainer.cpp:69
LOC
#define LOC
Definition: playlistcontainer.cpp:25
PlaylistContainer::cleanOutThreads
bool cleanOutThreads()
Definition: playlistcontainer.cpp:302
PlaylistLoadingThread::m_allMusic
AllMusic * m_allMusic
Definition: playlistcontainer.h:30
Playlist::copyTracks
void copyTracks(Playlist *to_ptr, bool update_display)
Definition: playlist.cpp:43
PlaylistContainer::m_myHost
QString m_myHost
Definition: playlistcontainer.h:81
PlaylistContainer::save
void save()
Definition: playlistcontainer.cpp:170
random
static long int random(void)
Definition: compat.h:149
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
PlaylistContainer::m_doneLoading
bool m_doneLoading
Definition: playlistcontainer.h:80
DEFAULT_STREAMLIST_NAME
#define DEFAULT_STREAMLIST_NAME
Definition: playlistcontainer.h:12
mythcontext.h
PlaylistContainer::m_allPlaylists
QList< Playlist * > * m_allPlaylists
Definition: playlistcontainer.h:77
Playlist::savePlaylist
void savePlaylist(const QString &a_name, const QString &a_host)
Definition: playlist.cpp:996
PlaylistContainer::m_activePlaylist
Playlist * m_activePlaylist
Definition: playlistcontainer.h:75
MSqlQuery::numRowsAffected
int numRowsAffected() const
Definition: mythdbcon.h:206
PlaylistContainer::m_lastPlayWeight
int m_lastPlayWeight
Definition: playlistcontainer.h:85
PlaylistContainer::clearActive
void clearActive()
Definition: playlistcontainer.cpp:312
PlaylistContainer::copyToActive
void copyToActive(int index)
Definition: playlistcontainer.cpp:206
Playlist::describeYourself
void describeYourself(void) const
Definition: playlist.cpp:475
Playlist::removeAllTracks
void removeAllTracks(void)
Definition: playlist.cpp:87
Playlist::getID
int getID(void) const
Definition: playlist.h:111
playlist.h
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:309
PlaylistContainer::renamePlaylist
void renamePlaylist(int index, QString new_name)
Definition: playlistcontainer.cpp:219
PlaylistLoadingThread::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: playlistcontainer.cpp:14
query
MSqlQuery query(MSqlQuery::InitCon())
PlaylistContainer::m_randomWeight
int m_randomWeight
Definition: playlistcontainer.h:86
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808