MythTV  master
streamview.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdlib>
3 
4 // qt
5 #include <QKeyEvent>
6 #include <QRegExp>
7 #include <QThread>
8 #include <QDomDocument>
9 
10 // myth
11 #include <mythcontext.h>
12 #include <mythdbcon.h>
13 #include <mythmainwindow.h>
14 #include <mythuibuttonlist.h>
15 #include <mythuibutton.h>
16 #include <mythuitext.h>
17 #include <mythuiprogressbar.h>
18 #include <mythuiutils.h>
19 #include <mythdialogbox.h>
20 #include <mythuihelper.h>
21 #include <mythdownloadmanager.h>
22 #include <mythdirs.h>
23 #include <musicutils.h>
24 #include <mythcoreutil.h>
25 
26 // mythmusic
27 #include "musicdata.h"
28 #include "musiccommon.h"
29 #include "streamview.h"
30 #include "musicplayer.h"
31 
32 using namespace std;
33 
34 
36  : MusicCommon(parent, parentScreen, "streamview")
37 {
39 }
40 
42 {
43  // Load the theme for this screen
44  bool err = LoadWindowFromXML("stream-ui.xml", "streamview", this);
45 
46  if (!err)
47  return false;
48 
49  // find common widgets available on any view
50  err = CreateCommon();
51 
52  // find widgets specific to this view
53  UIUtilE::Assign(this, m_streamList, "streamlist", &err);
54  UIUtilW::Assign(this, m_bufferStatus, "bufferstatus", &err);
55  UIUtilW::Assign(this, m_bufferProgress, "bufferprogress", &err);
56  UIUtilW::Assign(this, m_noStreams, "nostreams", &err);
57 
58  if (err)
59  {
60  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'streamview'");
61  return false;
62  }
63 
64  connect(m_streamList, SIGNAL(itemClicked(MythUIButtonListItem*)),
66  connect(m_streamList, SIGNAL(itemVisible(MythUIButtonListItem*)),
68 
70 
73 
75 
76  return true;
77 }
78 
80 {
81  MythMenu *menu = new MythMenu(tr("Stream Actions"), this, "mainmenu");
82  menu->AddItem(tr("Add Stream"));
83 
85  {
86  menu->AddItem(tr("Edit Stream"));
87  menu->AddItem(tr("Remove Stream"));
88  }
89 
90  menu->AddItem(MusicCommon::tr("Fullscreen Visualizer"), qVariantFromValue((int)MV_VISUALIZER));
91  menu->AddItem(MusicCommon::tr("Lyrics"), qVariantFromValue((int)MV_LYRICS));
92 
93  menu->AddItem(tr("More Options"), nullptr, createSubMenu());
94 
95  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
96 
97  MythDialogBox *menuPopup = new MythDialogBox(menu, popupStack, "actionmenu");
98 
99  if (menuPopup->Create())
100  popupStack->AddScreen(menuPopup);
101  else
102  delete menu;
103 }
104 
105 void StreamView::customEvent(QEvent *event)
106 {
107  bool handled = true;
108 
109  if (event->type() == MusicPlayerEvent::PlayedTracksChangedEvent)
110  {
111  if (gPlayer->getPlayedTracksList().count())
113 
114  // add the new track to the list
116  {
117  MusicMetadata *mdata = gPlayer->getPlayedTracksList().last();
118 
119  MythUIButtonListItem *item =
120  new MythUIButtonListItem(m_playedTracksList, "", qVariantFromValue(mdata), 0);
121 
122  InfoMap metadataMap;
123  mdata->toMap(metadataMap);
124  item->SetTextFromMap(metadataMap);
125  item->SetFontState("normal");
126  item->DisplayState("default", "playstate");
127  item->SetImage(mdata->getAlbumArtFile());
128 
130  }
131  }
132  else if (event->type() == MusicPlayerEvent::TrackChangeEvent)
133  {
134  MusicPlayerEvent *mpe = dynamic_cast<MusicPlayerEvent *>(event);
135 
136  if (!mpe)
137  return;
138 
139  if (m_streamList)
140  {
141  MythUIButtonListItem *item = m_streamList->GetItemByData(qVariantFromValue(m_currStream));
142  if (item)
143  {
144  item->SetFontState("normal");
145  item->DisplayState("default", "playstate");
146  }
147 
149  {
152  }
153 
154  item = m_streamList->GetItemByData(qVariantFromValue(m_currStream));
155  if (item)
156  {
157  if (gPlayer->isPlaying())
158  {
159  item->SetFontState("running");
160  item->DisplayState("playing", "playstate");
161  }
162  else if (gPlayer->isPaused())
163  {
164  item->SetFontState("idle");
165  item->DisplayState("paused", "playstate");
166  }
167  else
168  {
169  item->SetFontState("normal");
170  item->DisplayState("stopped", "playstate");
171  }
172  }
173  }
174 
176  }
177  else if (event->type() == OutputEvent::Playing)
178  {
179  if (gPlayer->isPlaying())
180  {
181  if (m_streamList)
182  {
183  MythUIButtonListItem *item = m_streamList->GetItemByData(qVariantFromValue(m_currStream));
184  if (item)
185  {
186  item->SetFontState("running");
187  item->DisplayState("playing", "playstate");
188  }
189  }
190  }
191 
192  // pass it on to the default handler in MusicCommon
193  handled = false;
194  }
195  else if (event->type() == OutputEvent::Stopped)
196  {
197  if (m_streamList)
198  {
199  MythUIButtonListItem *item = m_streamList->GetItemByData(qVariantFromValue(m_currStream));
200  if (item)
201  {
202  item->SetFontState("normal");
203  item->DisplayState("stopped", "playstate");
204  }
205  }
206 
207  // pass it on to the default handler in MusicCommon
208  handled = false;
209  }
210  else if (event->type() == OutputEvent::Buffering)
211  {
212  }
213  else if (event->type() == MythEvent::MythEventMessage)
214  {
215  MythEvent *me = static_cast<MythEvent *>(event);
216  QStringList tokens = me->Message().split(" ", QString::SkipEmptyParts);
217 
218  if (tokens.isEmpty())
219  return;
220 
221  if (tokens[0] == "DOWNLOAD_FILE")
222  {
223  QStringList args = me->ExtraDataList();
224 
225  if (tokens[1] == "UPDATE")
226  {
227  }
228  else if (tokens[1] == "FINISHED")
229  {
230  QString url = args[0];
231  int fileSize = args[2].toInt();
232  int errorCode = args[4].toInt();
233  QString filename = args[1];
234 
235  if ((errorCode != 0) || (fileSize == 0))
236  LOG(VB_GENERAL, LOG_ERR, QString("StreamView: failed to download radio icon from '%1'").arg(url));
237  else
238  {
239  for (int x = 0; x < m_streamList->GetCount(); x++)
240  {
242  MusicMetadata *mdata = item->GetData().value<MusicMetadata *>();
243  if (mdata && mdata->LogoUrl() == url)
244  item->SetImage(filename);
245  }
246  }
247  }
248  }
249  }
250  else if (event->type() == DecoderHandlerEvent::OperationStart)
251  {
252  DecoderHandlerEvent *dhe = dynamic_cast<DecoderHandlerEvent*>(event);
253  if (!dhe)
254  return;
255  if (dhe->getMessage() && m_bufferStatus)
256  {
258  }
259  }
260  else if (event->type() == DecoderHandlerEvent::BufferStatus)
261  {
262  DecoderHandlerEvent *dhe = dynamic_cast<DecoderHandlerEvent*>(event);
263  if (!dhe)
264  return;
265 
266  int available, maxSize;
267  dhe->getBufferStatus(&available, &maxSize);
268 
269  if (m_bufferStatus)
270  {
271  QString status = QString("%1%").arg((int)(100.0 / ((double)maxSize / (double)available)));
272  m_bufferStatus->SetText(status);
273  }
274 
275  if (m_bufferProgress)
276  {
277  m_bufferProgress->SetTotal(maxSize);
278  m_bufferProgress->SetUsed(available);
279  }
280  }
281  else if (event->type() == DecoderHandlerEvent::OperationStop)
282  {
283  if (m_bufferStatus)
285  }
286  else if (event->type() == DialogCompletionEvent::kEventType)
287  {
288  DialogCompletionEvent *dce = static_cast<DialogCompletionEvent*>(event);
289 
290  // make sure the user didn't ESCAPE out of the menu
291  if (dce->GetResult() < 0)
292  return;
293 
294  QString resultid = dce->GetId();
295  QString resulttext = dce->GetResultText();
296 
297  if (resultid == "mainmenu")
298  {
299  if (resulttext == tr("Add Stream"))
300  {
302  MythScreenType *screen = new EditStreamMetadata(mainStack, this, nullptr);
303 
304  if (screen->Create())
305  mainStack->AddScreen(screen);
306  else
307  delete screen;
308  }
309  else if (resulttext == tr("Remove Stream"))
310  {
311  removeStream();
312  }
313  else if (resulttext == tr("Edit Stream"))
314  {
315  editStream();
316  }
317  else
318  handled = false;
319  }
320  else
321  handled = false;
322  }
323  else
324  handled = false;
325 
326 
327  if (!handled)
329 }
330 
331 bool StreamView::keyPressEvent(QKeyEvent *event)
332 {
333  if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
334  return true;
335 
336  QStringList actions;
337  bool handled = GetMythMainWindow()->TranslateKeyPress("Music", event, actions);
338 
339  for (int i = 0; i < actions.size() && !handled; i++)
340  {
341  QString action = actions[i];
342  handled = true;
343 
344  if (action == "EDIT")
345  {
346  editStream();
347  }
348  else if (action == "DELETE")
349  {
350  removeStream();
351  }
352  else if (action == "TOGGLELAST")
353  {
355  {
356  m_streamList->SetValueByData(qVariantFromValue(m_lastStream));
357 
359  if (item)
360  streamItemClicked(item);
361  }
362  }
363  else
364  handled = false;
365  }
366 
367  if (!handled && MusicCommon::keyPressEvent(event))
368  handled = true;
369 
370  return handled;
371 }
372 
374 {
376  if (item)
377  {
378  MusicMetadata *mdata = item->GetData().value<MusicMetadata *>();
380  MythScreenType *screen = new EditStreamMetadata(mainStack, this, mdata);
381 
382  if (screen->Create())
383  mainStack->AddScreen(screen);
384  else
385  delete screen;
386  }
387 }
388 
390 {
392  if (item)
393  {
394  MusicMetadata *mdata = item->GetData().value<MusicMetadata *>();
395 
396  if (mdata)
397  ShowOkPopup(tr("Are you sure you want to delete this Stream?\n"
398  "Broadcaster: %1 - Channel: %2")
399  .arg(mdata->Broadcaster()).arg(mdata->Channel()),
400  this, SLOT(doRemoveStream(bool)), true);
401  }
402 }
403 
405 {
406  if (!ok)
407  return;
408 
410  if (item)
411  {
412  MusicMetadata *mdata = item->GetData().value<MusicMetadata *>();
413 
414  if (mdata)
415  deleteStream(mdata);
416  }
417 }
418 
420 {
421  if (!gPlayer->getCurrentPlaylist())
422  return;
423 
424  m_streamList->Reset();
425 
426  bool foundActiveStream = false;
427 
428  for (int x = 0; x < gPlayer->getCurrentPlaylist()->getTrackCount(); x++)
429  {
431  MythUIButtonListItem *item = new MythUIButtonListItem(m_streamList, "", qVariantFromValue(mdata));
432  InfoMap metadataMap;
433  if (mdata)
434  mdata->toMap(metadataMap);
435  item->SetTextFromMap(metadataMap);
436  item->SetText("", "imageloaded");
437  item->SetFontState("normal");
438  item->DisplayState("default", "playstate");
439 
440  // if this is the current radio stream update its play state to match the player
441  if (gPlayer->getCurrentMetadata() && mdata &&
442  mdata->ID() == gPlayer->getCurrentMetadata()->ID())
443  {
444  if (gPlayer->isPlaying())
445  {
446  item->SetFontState("running");
447  item->DisplayState("playing", "playstate");
448  }
449  else if (gPlayer->isPaused())
450  {
451  item->SetFontState("idle");
452  item->DisplayState("paused", "playstate");
453  }
454  else
455  {
456  item->SetFontState("normal");
457  item->DisplayState("stopped", "playstate");
458  }
459 
461 
463 
464  foundActiveStream = true;
465  }
466  }
467 
468  if (m_streamList->GetCount() > 0 && !foundActiveStream)
469  {
471  gPlayer->stop(true);
472  }
473 
474  if (m_noStreams)
476 
477  if (m_streamList->GetCount() == 0)
478  LOG(VB_GENERAL, LOG_ERR, "StreamView hasn't found any streams!");
479 }
480 
482 {
483  if (!item)
484  return;
485 
487 }
488 
490 {
491  if (!item)
492  return;
493 
494  if (!item->GetText("imageloaded").isEmpty())
495  return;
496 
497  MusicMetadata *mdata = item->GetData().value<MusicMetadata *>();
498  if (mdata)
499  {
500  if (!mdata->LogoUrl().isEmpty())
501  item->SetImage(mdata->getAlbumArtFile());
502  else
503  item->SetImage("");
504  }
505 
506  item->SetText(" ", "imageloaded");
507 }
508 
510 {
511  // sanity check this is a radio stream
512  int repo = ID_TO_REPO(mdata->ID());
513  if (repo != RT_Radio)
514  {
515  LOG(VB_GENERAL, LOG_ERR, "StreamView asked to add a stream but it isn't a radio stream!");
516  return;
517  }
518 
519  QString url = mdata->Url();
520 
522 
524 
526 
527  // find the new stream and make it the active item
528  for (int x = 0; x < m_streamList->GetCount(); x++)
529  {
531  MusicMetadata *itemsdata = item->GetData().value<MusicMetadata *>();
532  if (itemsdata)
533  {
534  if (url == itemsdata->Url())
535  {
537  break;
538  }
539  }
540  }
541 }
542 
544 {
545  // sanity check this is a radio stream
546  int repo = ID_TO_REPO(mdata->ID());
547  if (repo != RT_Radio)
548  {
549  LOG(VB_GENERAL, LOG_ERR, "StreamView asked to update a stream but it isn't a radio stream!");
550  return;
551  }
552 
553  MusicMetadata::IdType id = mdata->ID();
554 
556 
558 
559  // update mdata to point to the new item
560  mdata = gMusicData->m_all_streams->getMetadata(id);
561 
562  if (!mdata)
563  return;
564 
565  // force the icon to reload incase it changed
566  QFile::remove(mdata->getAlbumArtFile());
567  mdata->reloadAlbumArtImages();
568 
570 
571  // if we just edited the currently playing stream update the current metadata to match
572  MusicMetadata *currentMetadata = gPlayer->getCurrentMetadata();
573  if (id == currentMetadata->ID())
574  {
575  currentMetadata->setBroadcaster(mdata->Broadcaster());
576  currentMetadata->setChannel(mdata->Channel());
577  }
578 
579  // update the played tracks list to match the new metadata
580  if (m_playedTracksList)
581  {
582  for (int x = 0; x < m_playedTracksList->GetCount(); x++)
583  {
585  MusicMetadata *playedmdata = item->GetData().value<MusicMetadata *>();
586 
587  if (playedmdata && playedmdata->ID() == id)
588  {
589  playedmdata->setBroadcaster(mdata->Broadcaster());
590  playedmdata->setChannel(mdata->Channel());
591 
592  InfoMap metadataMap;
593  playedmdata->toMap(metadataMap);
594  item->SetTextFromMap(metadataMap);
595  }
596  }
597  }
598 
599  // find the stream and make it the active item
600  for (int x = 0; x < m_streamList->GetCount(); x++)
601  {
603  MusicMetadata *itemsdata = item->GetData().value<MusicMetadata *>();
604  if (itemsdata)
605  {
606  if (mdata->ID() == itemsdata->ID())
607  {
609  break;
610  }
611  }
612  }
613 }
614 
616 {
617  // sanity check this is a radio stream
618  int repo = ID_TO_REPO(mdata->ID());
619  if (repo != RT_Radio)
620  {
621  LOG(VB_GENERAL, LOG_ERR, "StreamView asked to delete a stream but it isn't a radio stream!");
622  return;
623  }
624 
625  int currPos = m_streamList->GetCurrentPos();
626  int topPos = m_streamList->GetTopItemPos();
627 
628  // if we are playing this radio stream stop playing
629  if (gPlayer->getCurrentMetadata() == mdata)
630  gPlayer->stop(true);
631 
633 
635 
637 
638  m_streamList->SetItemCurrent(currPos, topPos);
639 }
640 
642 
644 {
645  if (!LoadWindowFromXML("stream-ui.xml", "editstreammetadata", this))
646  return false;
647 
648  bool err = false;
649  UIUtilE::Assign(this, m_broadcasterEdit, "broadcasteredit", &err);
650  UIUtilE::Assign(this, m_channelEdit, "channeledit", &err);
651  UIUtilE::Assign(this, m_descEdit, "descriptionedit", &err);
652  UIUtilE::Assign(this, m_url1Edit, "url1edit", &err);
653  UIUtilE::Assign(this, m_url2Edit, "url2edit", &err);
654  UIUtilE::Assign(this, m_url3Edit, "url3edit", &err);
655  UIUtilE::Assign(this, m_url4Edit, "url4edit", &err);
656  UIUtilE::Assign(this, m_url5Edit, "url5edit", &err);
657  UIUtilE::Assign(this, m_logourlEdit, "logourledit" , &err);
658  UIUtilE::Assign(this, m_genreEdit, "genreedit", &err);
659  UIUtilE::Assign(this, m_languageEdit, "languageedit", &err);
660  UIUtilE::Assign(this, m_countryEdit, "countryedit", &err);
661  UIUtilE::Assign(this, m_formatEdit, "formatedit", &err);
662  UIUtilE::Assign(this, m_saveButton, "savebutton", &err);
663  UIUtilE::Assign(this, m_cancelButton, "cancelbutton", &err);
664  UIUtilE::Assign(this, m_searchButton, "searchbutton", &err);
665 
666  if (err)
667  {
668  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'editstreampopup'");
669  return false;
670  }
671 
672  if (m_streamMeta)
673  {
687  }
688  else
689  m_formatEdit->SetText("%a - %t");
690 
691  connect(m_searchButton, SIGNAL(Clicked()), this, SLOT(searchClicked()));
692  connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(Close()));
693  connect(m_saveButton, SIGNAL(Clicked()), this, SLOT(saveClicked()));
694 
695  BuildFocusList();
696 
697  return true;
698 }
699 
701 {
703  MythScreenType *screen = new SearchStream(mainStack, this);
704 
705  if (screen->Create())
706  mainStack->AddScreen(screen);
707  else
708  delete screen;
709 
710 }
711 
713 {
714  bool doUpdate = true;
715 
716  if (!m_streamMeta)
717  {
720  doUpdate = false;
721  }
722 
730  m_streamMeta->setFormat("cast");
737 
738  if (doUpdate)
740  else
742 
743  Close();
744 }
745 
747 {
748  if (mdata)
749  {
751  m_channelEdit->SetText(mdata->Channel());
752  m_url1Edit->SetText(mdata->Url(0));
753  m_url2Edit->SetText(mdata->Url(1));
754  m_url3Edit->SetText(mdata->Url(2));
755  m_url4Edit->SetText(mdata->Url(3));
756  m_url5Edit->SetText(mdata->Url(4));
757  m_logourlEdit->SetText(mdata->LogoUrl());
758  m_genreEdit->SetText(mdata->Genre());
760  m_descEdit->SetText(mdata->Description());
761  m_countryEdit->SetText(mdata->Country());
762  m_languageEdit->SetText(mdata->Language());
763  }
764 }
765 
767 
769 {
770  if (!LoadWindowFromXML("stream-ui.xml", "searchstream", this))
771  return false;
772 
773  bool err = false;
774  UIUtilE::Assign(this, m_broadcasterList, "broadcasterlist", &err);
775  UIUtilE::Assign(this, m_genreList, "genrelist", &err);
776  UIUtilW::Assign(this, m_languageList, "languagelist", &err);
777  UIUtilW::Assign(this, m_countryList, "countrylist", &err);
778  UIUtilE::Assign(this, m_streamList, "streamlist", &err);
779  UIUtilE::Assign(this, m_channelEdit, "channeledit", &err);
780  UIUtilE::Assign(this, m_matchesText, "matchestext", &err);
781 
782  if (err)
783  {
784  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'searchstream'");
785  return false;
786  }
787 
790  m_matchesText->SetText("");
791 
792  connect(m_streamList, SIGNAL(itemClicked(MythUIButtonListItem*)),
793  this, SLOT(streamClicked(MythUIButtonListItem*)));
794  connect(m_streamList, SIGNAL(itemVisible(MythUIButtonListItem*)),
795  this, SLOT(streamVisible(MythUIButtonListItem*)));
796  connect(m_broadcasterList, SIGNAL(itemSelected(MythUIButtonListItem*)),
797  this, SLOT(updateStreams()));
798  connect(m_genreList, SIGNAL(itemSelected(MythUIButtonListItem*)),
799  this, SLOT(updateStreams()));
800  connect(m_countryList, SIGNAL(itemSelected(MythUIButtonListItem*)),
801  this, SLOT(updateStreams()));
802 
803 
804  if (m_countryList)
805  {
807  connect(m_languageList, SIGNAL(itemSelected(MythUIButtonListItem*)),
808  this, SLOT(updateStreams()));
809  }
810 
811  if (m_languageList)
812  {
814  connect(m_channelEdit, SIGNAL(valueChanged()),
815  this, SLOT(updateStreams()));
816  }
817 
818  connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(doUpdateStreams()));
819 
820  LoadInBackground("Loading Streams...");
821 
822  BuildFocusList();
823 
824  return true;
825 }
826 
828 {
829  loadStreams();
830  QTimer::singleShot(0, this, SLOT(doneLoading(void)));
831 }
832 
834 {
836  updateGenres();
837  updateLanguages();
838  updateCountries();
839  doUpdateStreams();
840 }
841 
843 {
844  if (!item)
845  return;
846 
847  MusicMetadata mdata = item->GetData().value<MusicMetadata>();
849 
850  Close();
851 }
852 
854 {
855  if (!item)
856  return;
857 
858  MusicMetadata mdata = item->GetData().value<MusicMetadata>();
859  if (!mdata.LogoUrl().isEmpty() && mdata.LogoUrl() != "-")
860  {
861  if (item->GetText("dummy") == " ")
862  {
863  item->SetImage(mdata.LogoUrl());
864  item->SetText("", "dummy");
865  }
866  }
867 }
868 
870 {
872 }
873 
875 {
877 
878  new MythUIButtonListItem(m_broadcasterList, tr("<All Broadcasters>"));
879 
880  MSqlQuery query(MSqlQuery::InitCon());
881 
882  query.prepare("SELECT DISTINCT broadcaster FROM music_streams ORDER BY broadcaster;");
883 
884  if (!query.exec() || !query.isActive())
885  {
886  MythDB::DBError("get broadcaster", query);
887  return;
888  }
889 
890  while (query.next())
891  {
892  new MythUIButtonListItem(m_broadcasterList, query.value(0).toString());
893  }
894 
895  m_broadcasterList->SetValue(tr("<All Broadcasters>"));
896 }
897 
899 {
900  m_genreList->Reset();
901 
902  new MythUIButtonListItem(m_genreList, tr("<All Genres>"));
903 
904  MSqlQuery query(MSqlQuery::InitCon());
905 
906  query.prepare("SELECT DISTINCT genre FROM music_streams ORDER BY genre;");
907 
908  if (!query.exec() || !query.isActive())
909  {
910  MythDB::DBError("get genres", query);
911  return;
912  }
913 
914  while (query.next())
915  {
916  new MythUIButtonListItem(m_genreList, query.value(0).toString());
917  }
918 
919  m_genreList->SetValue(tr("<All Genres>"));
920 }
921 
923 {
924  if (m_countryList)
925  {
926  m_countryList->Reset();
927 
928  new MythUIButtonListItem(m_countryList, tr("<All Countries>"));
929 
930  MSqlQuery query(MSqlQuery::InitCon());
931 
932  query.prepare("SELECT DISTINCT country FROM music_streams ORDER BY country;");
933 
934  if (!query.exec() || !query.isActive())
935  {
936  MythDB::DBError("get countries", query);
937  return;
938  }
939 
940  while (query.next())
941  {
942  new MythUIButtonListItem(m_countryList, query.value(0).toString());
943  }
944 
945  m_countryList->SetValue(tr("<All Countries>"));
946  }
947 }
948 
950 {
951  if (m_languageList)
952  {
954 
955  new MythUIButtonListItem(m_languageList, tr("<All Languages>"));
956 
957  MSqlQuery query(MSqlQuery::InitCon());
958 
959  query.prepare("SELECT DISTINCT language FROM music_streams ORDER BY language;");
960 
961  if (!query.exec() || !query.isActive())
962  {
963  MythDB::DBError("get languages", query);
964  return;
965  }
966 
967  while (query.next())
968  {
969  new MythUIButtonListItem(m_languageList, query.value(0).toString());
970  }
971 
972  m_languageList->SetValue(tr("<All Languages>"));
973  }
974 }
975 
977 {
978  if (m_updateTimer.isActive())
979  m_updateTimer.stop();
980 
981  m_updateTimer.start(500);
982 }
983 
985 {
986  if (m_updating)
987  return;
988 
989  QString broadcaster = m_broadcasterList->GetValue();
990  QString genre = m_genreList->GetValue();
991  QString language = m_languageList ? m_languageList->GetValue() : tr("<All Languages>");
992  QString country = m_countryList ? m_countryList->GetValue() : tr("<All Countries>");
993  QString channel = m_channelEdit->GetText();
994 
995  // only update the buttonlist if something changed
996  if (m_oldBroadcaster == broadcaster && m_oldGenre == genre && m_oldChannel == channel &&
997  m_oldLanguage == language && m_oldCountry == country)
998  return;
999 
1000  m_oldBroadcaster = broadcaster;
1001  m_oldGenre = genre;
1002  m_oldChannel = channel;
1003  m_oldLanguage = language;
1004  m_oldCountry = country;
1005 
1006  bool searchBroadcaster = (broadcaster != tr("<All Broadcasters>"));
1007  bool searchGenre = (genre != tr("<All Genres>"));
1008  bool searchLanguage = (language != tr("<All Languages>"));
1009  bool searchCountry = (country != tr("<All Countries>"));
1010  bool searchChannel = !channel.isEmpty();
1011 
1012  m_streams.clear();
1013  m_streamList->Reset();
1014 
1015  MSqlQuery query(MSqlQuery::InitCon());
1016 
1017  QString sql = "SELECT broadcaster, channel, description, genre, url1, url2, url3, url4, url5, "
1018  "logourl, metaformat, country, language "
1019  "FROM music_streams ";
1020  bool doneWhere = false;
1021 
1022  if (searchBroadcaster)
1023  {
1024  sql += "WHERE broadcaster = :BROADCASTER ";
1025  doneWhere = true;
1026  }
1027 
1028  if (searchGenre)
1029  {
1030  if (!doneWhere)
1031  {
1032  sql += "WHERE genre = :GENRE ";
1033  doneWhere = true;
1034  }
1035  else
1036  sql += "AND genre = :GENRE ";
1037  }
1038 
1039  if (searchLanguage)
1040  {
1041  if (!doneWhere)
1042  {
1043  sql += "WHERE language = :LANGUAGE ";
1044  doneWhere = true;
1045  }
1046  else
1047  sql += "AND language = :LANGUAGE ";
1048  }
1049 
1050  if (searchCountry)
1051  {
1052  if (!doneWhere)
1053  {
1054  sql += "WHERE country = :COUNTRY ";
1055  doneWhere = true;
1056  }
1057  else
1058  sql += "AND country = :COUNTRY ";
1059  }
1060 
1061  if (searchChannel)
1062  {
1063  if (!doneWhere)
1064  {
1065  sql += "WHERE channel LIKE " + QString("'%%1%'").arg(channel);
1066  // doneWhere = true;
1067  }
1068  else
1069  sql += "AND channel LIKE " + QString("'%%1%' ").arg(channel);
1070  }
1071 
1072  sql += "ORDER BY broadcaster, channel;";
1073 
1074  query.prepare(sql);
1075 
1076  if (searchBroadcaster)
1077  query.bindValue(":BROADCASTER", broadcaster);
1078 
1079  if (searchGenre)
1080  query.bindValue(":GENRE", genre);
1081 
1082  if (searchLanguage)
1083  query.bindValue(":LANGUAGE", language);
1084 
1085  if (searchCountry)
1086  query.bindValue(":COUNTRY", country);
1087 
1088  if (!query.exec() || !query.isActive())
1089  {
1090  MythDB::DBError("search streams", query);
1091  return;
1092  }
1093 
1094  if (query.size() > 500)
1095  {
1096  QString message = tr("Updating stream list. Please Wait ...");
1097  OpenBusyPopup(message);
1098  }
1099 
1100  int count = 0;
1101  while (query.next())
1102  {
1103  MusicMetadata mdata;
1104  mdata.setBroadcaster(query.value(0).toString());
1105  mdata.setChannel(query.value(1).toString());
1106  mdata.setDescription(query.value(2).toString());
1107  mdata.setGenre(query.value(3).toString());
1108 
1109  for (int x = 0; x < STREAMURLCOUNT; x++)
1110  mdata.setUrl(query.value(4 + x).toString(), x);
1111 
1112  mdata.setLogoUrl(query.value(9).toString());
1113  mdata.setMetadataFormat(query.value(10).toString());
1114  mdata.setCountry(query.value(11).toString());
1115  mdata.setLanguage(query.value(12).toString());
1116 
1117  MythUIButtonListItem *item = new MythUIButtonListItem(m_streamList, "", qVariantFromValue(mdata));
1118  InfoMap metadataMap;
1119  mdata.toMap(metadataMap);
1120 
1121  item->SetTextFromMap(metadataMap);
1122 
1123  item->SetText(" ", "dummy");
1124  count++;
1125 
1126  if ((count % 500) == 0)
1127  {
1128  qApp->processEvents();
1129  }
1130  }
1131 
1132  m_matchesText->SetText(QString("%1").arg(m_streamList->GetCount()));
1133 
1134  if (query.size() > 500)
1135  CloseBusyPopup();
1136 
1137  m_updating = false;
1138 }
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
#define ID_TO_REPO(x)
Definition: musicmetadata.h:69
MusicMetadata * getSongAt(int pos) const
Definition: playlist.cpp:1085
MythUIButtonList * m_streamList
Definition: streamview.h:48
void setPlayMode(PlayMode mode)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
void streamItemVisible(MythUIButtonListItem *item)
Definition: streamview.cpp:489
QString m_oldCountry
Definition: streamview.h:131
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
bool keyPressEvent(QKeyEvent *) override
Key event handler.
Definition: streamview.cpp:331
MusicMetadata * getCurrentMetadata(void)
get the metadata for the current track in the playlist
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
MythUITextEdit * m_descEdit
Definition: streamview.h:81
QString Url(uint index=0)
Playlist * getCurrentPlaylist(void)
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
void deleteStream(MusicMetadata *mdata)
Definition: streamview.cpp:615
bool Create() override
Definition: streamview.cpp:643
void editStream(void)
Definition: streamview.cpp:373
static Type Playing
Definition: output.h:61
QString LogoUrl(void)
QString m_oldGenre
Definition: streamview.h:129
static Type MythEventMessage
Definition: mythevent.h:66
MythUITextEdit * m_url4Edit
Definition: streamview.h:85
QString Language(void)
MusicView m_currentView
Definition: musiccommon.h:139
virtual void SetValue(int value)
void updateStreams(void)
Definition: streamview.cpp:976
void updateStream(MusicMetadata *mdata)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
int GetTopItemPos(void) const
QString Genre() const
virtual bool Create(void)
Basic menu dialog, message and a list of options.
void updateStreamList(void)
Definition: streamview.cpp:419
void addStream(MusicMetadata *mdata)
void setBroadcaster(const QString &broadcaster)
void setLanguage(const QString &language)
void customEvent(QEvent *event) override
MythUIButton * m_cancelButton
Definition: streamview.h:94
AllStream * m_all_streams
Definition: musicdata.h:55
MusicMetadata * m_lastStream
Definition: streamview.h:54
bool setCurrentTrackPos(int pos)
int size(void) const
Definition: mythdbcon.h:203
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:136
void changeStreamMetadata(MusicMetadata *mdata)
Definition: streamview.cpp:746
bool isPlaying(void)
Definition: musicplayer.h:102
MythUIText * m_noStreams
Definition: streamview.h:49
QString MetadataFormat(void)
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
Definition: streamview.cpp:827
MythScreenStack * GetStack(const QString &stackname)
MythUITextEdit * m_formatEdit
Definition: streamview.h:88
MythScreenStack * GetMainStack()
Events sent by the DecoderHandler and it's helper classes.
QString Country(void)
MythUIButtonListItem * GetItemAt(int pos) const
void setLogoUrl(const QString &logourl)
static MythThemedMenu * menu
QTimer m_updateTimer
Definition: streamview.h:142
MythUITextEdit * m_countryEdit
Definition: streamview.h:90
#define STREAMURLCOUNT
Definition: musicmetadata.h:74
void customEvent(QEvent *event) override
Definition: streamview.cpp:105
void BuildFocusList(void)
static Type Buffering
Definition: output.h:62
static Type kEventType
Definition: mythdialogbox.h:50
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
void reloadAlbumArtImages(void)
static Type TrackChangeEvent
Definition: musicplayer.h:40
QVariant value(int i) const
Definition: mythdbcon.h:198
virtual void Close()
void loadStreamPlaylist(void)
MythUIButtonListItem * GetItemByData(const QVariant &data)
virtual void SetVisible(bool visible)
MythUIProgressBar * m_bufferProgress
Definition: streamview.h:51
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
static bool updateStreamList(void)
QString m_oldChannel
Definition: streamview.h:130
MythUITextEdit * m_languageEdit
Definition: streamview.h:91
This class is used as a container for messages.
Definition: mythevent.h:16
MusicMetadata * m_streamMeta
Definition: streamview.h:77
QString Channel(void)
QString m_oldLanguage
Definition: streamview.h:132
void streamItemClicked(MythUIButtonListItem *item)
Definition: streamview.cpp:481
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MythUIButtonList * m_streamList
Definition: streamview.h:139
MythUIButtonList * m_playedTracksList
Definition: musiccommon.h:204
MythUIText * m_matchesText
Definition: streamview.h:140
int getTrackCount(void)
Definition: playlist.h:79
MythUITextEdit * m_url1Edit
Definition: streamview.h:82
void updateTrackInfo(MusicMetadata *mdata)
MusicMetadata * getMetadata(MusicMetadata::IdType an_id)
QString * getMessage(void) const
IdType ID() const
void setChannel(const QString &channel)
void searchClicked(void)
Definition: streamview.cpp:700
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:84
QList< MusicMetadata * > & getPlayedTracksList(void)
Definition: musicplayer.h:130
bool isActive(void) const
Definition: mythdbcon.h:204
QString getAlbumArtFile(void)
void OpenBusyPopup(const QString &message="")
static Type OperationStart
void setRepo(RepoType repo)
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
void SetText(const QString &text, const QString &name="", const QString &state="")
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythUIText * m_bufferStatus
Definition: streamview.h:50
void doUpdateStreams(void)
Definition: streamview.cpp:984
void updateBroadcasters(void)
Definition: streamview.cpp:874
void setFormat(const QString &lformat)
MythUIButtonList * m_languageList
Definition: streamview.h:137
void stop(bool stopAll=false)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void updateLanguages(void)
Definition: streamview.cpp:949
void SetText(const QString &text, bool moveCursor=true)
MythUIType * GetFocusWidget(void) const
MythUIButtonList * m_genreList
Definition: streamview.h:135
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
MythUITextEdit * m_channelEdit
Definition: streamview.h:80
QString GetText(const QString &name="") const
virtual QString GetValue() const
void setUrl(const QString &url, uint index=0)
EditStreamMetadata * m_parent
Definition: streamview.h:123
QString m_oldBroadcaster
Definition: streamview.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
MythUITextEdit * m_url5Edit
Definition: streamview.h:86
void streamClicked(MythUIButtonListItem *item)
Definition: streamview.cpp:842
void CloseBusyPopup(void)
QString Description(void)
MusicMetadata * m_currStream
Definition: streamview.h:53
void updateStream(MusicMetadata *mdata)
Definition: streamview.cpp:543
MythUITextEdit * m_url2Edit
Definition: streamview.h:83
StreamView(MythScreenStack *parent, MythScreenType *parentScreen)
Definition: streamview.cpp:35
bool isPaused(void)
Definition: musicplayer.h:103
QList< MusicMetadata > m_streams
Definition: streamview.h:124
void updateGenres(void)
Definition: streamview.cpp:898
void streamVisible(MythUIButtonListItem *item)
Definition: streamview.cpp:853
void updateUIPlayedList(void)
void addStream(MusicMetadata *mdata)
Definition: streamview.cpp:509
void SetFontState(const QString &state, const QString &name="")
void setMetadataFormat(const QString &metaformat)
static Type BufferStatus
void setDescription(const QString &description)
void updateCountries(void)
Definition: streamview.cpp:922
MusicData * gMusicData
Definition: musicdata.cpp:20
MythUITextEdit * m_genreEdit
Definition: streamview.h:89
MythUITextEdit * m_logourlEdit
Definition: streamview.h:87
void getBufferStatus(int *available, int *maxSize) const
MythMenu * createSubMenu(void)
StreamView * m_parent
Definition: streamview.h:75
bool m_updating
Definition: streamview.h:143
void SetItemCurrent(MythUIButtonListItem *item)
static Type OperationStop
bool Create() override
Definition: streamview.cpp:768
static Type PlayedTracksChangedEvent
Definition: musicplayer.h:51
void removeStream(MusicMetadata *mdata)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MythUIButton * m_searchButton
Definition: streamview.h:93
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
Screen in which all other widgets are contained and rendered.
void removeStream(void)
Definition: streamview.cpp:389
int GetCurrentPos() const
const QString & Message() const
Definition: mythevent.h:58
QString Broadcaster(void)
void saveClicked(void)
Definition: streamview.cpp:712
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
void DisplayState(const QString &state, const QString &name)
void SetTextFromMap(const InfoMap &infoMap, const QString &state="")
bool Create(void) override
Definition: streamview.cpp:41
MythUIButtonList * m_countryList
Definition: streamview.h:136
uint32_t IdType
Definition: musicmetadata.h:84
const QStringList & ExtraDataList() const
Definition: mythevent.h:60
void doneLoading(void)
Definition: streamview.cpp:833
MythUIButton * m_saveButton
Definition: streamview.h:95
MythUITextEdit * m_channelEdit
Definition: streamview.h:138
void loadStreams(void)
Definition: streamview.cpp:869
void toMap(InfoMap &metadataMap, const QString &prefix="")
MythUITextEdit * m_url3Edit
Definition: streamview.h:84
void doRemoveStream(bool ok)
Definition: streamview.cpp:404
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
bool CreateCommon(void)
Definition: musiccommon.cpp:84
QString GetText(void) const
void ShowMenu(void) override
Definition: streamview.cpp:79
void SetValueByData(const QVariant &data)
MythUIButtonListItem * GetItemCurrent() const
void LoadInBackground(QString message="")
bool Create(void) override
MythUITextEdit * m_broadcasterEdit
Definition: streamview.h:79
static Type Stopped
Definition: output.h:65
void setCountry(const QString &country)
void setGenre(const QString &lgenre)
MythUIButtonList * m_broadcasterList
Definition: streamview.h:134