00001 #include <cstdlib>
00002 #include <iostream>
00003 using namespace std;
00004
00005
00006 #include <qapplication.h>
00007 #include <qstringlist.h>
00008 #include <qpixmap.h>
00009 #include <qregexp.h>
00010 #include <qframe.h>
00011 #include <qlayout.h>
00012 #include <qevent.h>
00013
00014
00015 #include <mythtv/dialogbox.h>
00016 #include <mythtv/mythcontext.h>
00017 #include <mythtv/lcddevice.h>
00018 #include <mythtv/uitypes.h>
00019 #include <mythtv/uilistbtntype.h>
00020 #include <mythtv/mythmediamonitor.h>
00021
00022
00023 #include "metadata.h"
00024 #include "databasebox.h"
00025 #include "treecheckitem.h"
00026 #include "cddecoder.h"
00027 #include "playlist.h"
00028 #include "musicplayer.h"
00029 #ifndef USING_MINGW
00030 #include "cddecoder.h"
00031 #endif
00032
00033 DatabaseBox::DatabaseBox(MythMainWindow *parent,
00034 const QString dev, const QString &window_name,
00035 const QString &theme_filename, const char *name)
00036 : MythThemedDialog(parent, window_name, theme_filename, name)
00037 {
00038 m_CDdevice = dev;
00039 active_playlist = NULL;
00040
00041 if (!gMusicData->all_music)
00042 {
00043 VERBOSE(VB_IMPORTANT, "We are not going to get very far with a null "
00044 "pointer to metadata");
00045 exit(0);
00046 }
00047
00048
00049 cd_checking_flag = false;
00050 cd_checking_flag = gContext->GetNumSetting("AutoLookupCD");
00051
00052 QString treelev = gContext->GetSetting("TreeLevels", "artist album title");
00053 QStringList treelevels = QStringList::split(" ", treelev.lower());
00054
00055 active_popup = NULL;
00056 active_pl_edit = NULL;
00057
00058 playlist_popup = NULL;
00059
00060 cditem = NULL;
00061 holding_track = false;
00062
00063 tree = getUIListTreeType("musictree");
00064 if (!tree)
00065 {
00066 DialogBox *dlg = new DialogBox(
00067 gContext->GetMainWindow(),
00068 QObject::tr(
00069 "The theme you are using does not contain the "
00070 "%1 element. Please contact the theme creator "
00071 "and ask if they could please update it.<br><br>"
00072 "The next screen will be empty. "
00073 "Escape out of it to return to the menu.")
00074 .arg("'musictree'"));
00075
00076 dlg->AddButton(tr("OK"));
00077 dlg->exec();
00078 dlg->deleteLater();
00079
00080 return;
00081 }
00082
00083 UITextType *line = NULL;
00084
00085 for (int i = 1; i <= 6; i++)
00086 {
00087 QString linename = QString("line%1").arg(i);
00088 if ((line = getUITextType(linename)))
00089 m_lines.append(line);
00090 }
00091
00092 if (m_lines.count() < 3)
00093 {
00094 DialogBox *dlg = new DialogBox(
00095 gContext->GetMainWindow(),
00096 tr("The theme you are using does not contain any info "
00097 "lines in the music element. Please contact the theme "
00098 "creator and ask if they could please update it."));
00099
00100 dlg->AddButton(tr("OK"));
00101 dlg->exec();
00102 dlg->deleteLater();
00103 }
00104
00105 connect(tree, SIGNAL(itemEntered(UIListTreeType *, UIListGenericTree *)),
00106 this, SLOT(entered(UIListTreeType *, UIListGenericTree *)));
00107
00108
00109
00110
00111 rootNode = new UIListGenericTree(NULL, "Root Music Node");
00112
00113 allmusic = new TreeCheckItem(rootNode, tr("All My Music"), "genre", 0);
00114 if (cd_checking_flag)
00115 cditem = new CDCheckItem(rootNode, tr("Blechy Blech Blah"), "cd", 0);
00116 alllists = new TreeCheckItem(rootNode, tr("All My Playlists"), "genre", 0);
00117 allcurrent = new PlaylistTitle(rootNode, tr("Active Play Queue"));
00118
00119 tree->SetTree(rootNode);
00120
00121 cd_reader_thread = NULL;
00122 if (cd_checking_flag)
00123 {
00124
00125
00126
00127 cd_reader_thread = new ReadCDThread(m_CDdevice);
00128
00129
00130 fillCD();
00131
00132 cd_reader_thread->start();
00133
00134 cd_watcher = new QTimer(this);
00135 connect(cd_watcher, SIGNAL(timeout()), this, SLOT(occasionallyCheckCD()));
00136 cd_watcher->start(1000);
00137 }
00138
00139
00140
00141
00142 wait_counter = 0;
00143 numb_wait_dots = 0;
00144 fill_list_timer = new QTimer(this);
00145 connect(fill_list_timer, SIGNAL(timeout()), this, SLOT(keepFilling()));
00146 fill_list_timer->start(20);
00147 }
00148
00149 DatabaseBox::~DatabaseBox()
00150 {
00151 if (cd_reader_thread)
00152 {
00153 cd_watcher->stop();
00154
00155 cd_reader_thread->wait();
00156 delete cd_reader_thread;
00157 }
00158
00159 gMusicData->all_music->cleanOutThreads();
00160 gMusicData->all_playlists->cleanOutThreads();
00161
00162 gMusicData->all_music->resetListings();
00163
00164 gMusicData->all_playlists->getActive()->removeAllWidgets();
00165
00166 if (class LCD * lcd = LCD::Get())
00167 lcd->switchToTime();
00168
00169 delete rootNode;
00170
00171 gContext->SaveSetting("MusicBookmark", "");
00172 gContext->SaveSetting("MusicBookmarkPosition", 0);
00173 }
00174
00175 void DatabaseBox::showWaiting()
00176 {
00177 wait_counter++;
00178 if (wait_counter > 10)
00179 {
00180 wait_counter = 0;
00181 ++numb_wait_dots;
00182 if (numb_wait_dots > 3)
00183 numb_wait_dots = 1;
00184
00185 QString a_string = tr("All My Music ~ Loading Music Data ");
00186
00187 if (class LCD * lcd = LCD::Get())
00188 {
00189
00190 QPtrList<LCDTextItem> textItems;
00191 textItems.setAutoDelete(true);
00192
00193 textItems.append(new LCDTextItem(1, ALIGN_CENTERED,
00194 tr("Loading Music Data"), "Generic", false));
00195 lcd->switchToGeneric(&textItems);
00196 }
00197
00198 for (int i = 0; i < numb_wait_dots; i++)
00199 a_string += ".";
00200
00201 allmusic->setText(a_string);
00202 }
00203 }
00204
00205 void DatabaseBox::keepFilling()
00206 {
00207 if (gMusicData->all_music->doneLoading() &&
00208 gMusicData->all_playlists->doneLoading())
00209 {
00210
00211 if (gMusicData->all_music->putYourselfOnTheListView(allmusic))
00212 {
00213 allmusic->setText(tr("All My Music"));
00214 fill_list_timer->stop();
00215 gMusicData->all_playlists->setActiveWidget(allcurrent);
00216 active_playlist = gMusicData->all_playlists->getActive();
00217 active_playlist->putYourselfOnTheListView(allcurrent);
00218 gMusicData->all_playlists->showRelevantPlaylists(alllists);
00219
00220 checkTree();
00221
00222
00223 if (class LCD * lcd = LCD::Get())
00224 lcd->switchToTime();
00225 }
00226 else
00227 showWaiting();
00228 }
00229 else
00230 showWaiting();
00231 }
00232
00233 void DatabaseBox::occasionallyCheckCD()
00234 {
00235 if (cd_reader_thread->getLock()->locked())
00236 return;
00237
00238 if (cd_reader_thread->statusChanged())
00239 {
00240 if (active_playlist)
00241 {
00242 active_playlist->ripOutAllCDTracksNow();
00243 fillCD();
00244 }
00245 }
00246 if (!cd_reader_thread->running())
00247 cd_reader_thread->start();
00248 }
00249
00250 void DatabaseBox::copyNewPlaylist()
00251 {
00252 if (!active_popup)
00253 return;
00254
00255 if (active_pl_edit->text().length() < 1)
00256 {
00257 closeActivePopup();
00258 return;
00259 }
00260
00261 if (gMusicData->all_playlists->nameIsUnique(active_pl_edit->text(), 0))
00262 {
00263 gMusicData->all_playlists->copyNewPlaylist(active_pl_edit->text());
00264 gMusicData->all_playlists->showRelevantPlaylists(alllists);
00265 checkTree();
00266 closeActivePopup();
00267 }
00268 else
00269 {
00270
00271 }
00272 }
00273
00274
00275 void DatabaseBox::renamePlaylist()
00276 {
00277 if (!playlist_popup)
00278 return;
00279
00280 if (playlist_rename->text().length() < 1)
00281 {
00282 closePlaylistPopup();
00283 return;
00284 }
00285
00286 UIListGenericTree *item = tree->GetCurrentPosition();
00287
00288 if (TreeCheckItem *rename_item = dynamic_cast<TreeCheckItem*>(item) )
00289 {
00290 if (rename_item->getID() < 0)
00291 {
00292 if (gMusicData->all_playlists->nameIsUnique(playlist_rename->text(),
00293 rename_item->getID() * -1))
00294 {
00295 gMusicData->all_playlists->renamePlaylist(rename_item->getID() * -1,
00296 playlist_rename->text());
00297 rename_item->setText(playlist_rename->text());
00298 tree->Redraw();
00299 closePlaylistPopup();
00300 }
00301 else
00302 {
00303
00304 }
00305 }
00306 else
00307 {
00308 VERBOSE(VB_IMPORTANT, "Trying to rename something that doesn't "
00309 "seem to be a playlist");
00310 }
00311 }
00312 }
00313
00314 void DatabaseBox::popBackPlaylist()
00315 {
00316 if (!active_popup)
00317 return;
00318
00319 gMusicData->all_playlists->popBackPlaylist();
00320 gMusicData->all_playlists->showRelevantPlaylists(alllists);
00321 checkTree();
00322
00323 closeActivePopup();
00324 }
00325
00326 void DatabaseBox::clearActive()
00327 {
00328 if (!active_popup)
00329 return;
00330
00331 closeActivePopup();
00332
00333 gMusicData->all_playlists->clearActive();
00334 gMusicData->all_playlists->showRelevantPlaylists(alllists);
00335 checkTree();
00336 }
00337
00338 void DatabaseBox::CreateCDAudio()
00339 {
00340 int error;
00341
00342 if (!active_popup)
00343 return;
00344
00345 closeActivePopup();
00346
00347
00348
00349 error = active_playlist->CreateCDAudio();
00350
00351 error_popup = NULL;
00352
00353 if (error)
00354 ErrorPopup(tr("Couldn't create CD"));
00355 else
00356 ErrorPopup(tr("CD Created"));
00357 }
00358
00359 void DatabaseBox::CreateCDMP3()
00360 {
00361 int error;
00362 if (!active_popup)
00363 return;
00364
00365 closeActivePopup();
00366
00367
00368
00369 error = active_playlist->CreateCDMP3();
00370
00371 error_popup=NULL;
00372
00373 if (error)
00374 ErrorPopup(tr("Couldn't create CD"));
00375 else
00376 ErrorPopup(tr("CD Created"));
00377 }
00378
00379 void DatabaseBox::ErrorPopup(const QString &msg)
00380 {
00381 if (error_popup)
00382 return;
00383
00384 error_popup = new MythPopupBox(gContext->GetMainWindow(),
00385 "playlist_popup");
00386
00387 error_popup->addLabel(msg);
00388
00389 QButton *mac_b =error_popup->addButton(tr("OK"), this,
00390 SLOT(closeErrorPopup()));
00391
00392 int x = (int)(100 * wmult);
00393 int y = (int)(100 * hmult);
00394
00395 error_popup->ShowPopupAtXY(x, y, this, SLOT(closeErrorPopup()));
00396 mac_b->setFocus();
00397 }
00398
00399 void DatabaseBox::closeErrorPopup(void)
00400 {
00401 if (!error_popup)
00402 return;
00403
00404 error_popup->hide();
00405 error_popup->deleteLater();
00406 error_popup = NULL;
00407 }
00408
00409 void DatabaseBox::BlankCDRW()
00410 {
00411 char command[1024];
00412
00413 if (!active_popup)
00414 return;
00415
00416 closeActivePopup();
00417
00418
00419 if (!gContext->GetNumSetting("CDWriterEnabled"))
00420 {
00421 VERBOSE(VB_GENERAL, "Writer is not enabled. We cannot be here!");
00422 return;
00423 }
00424
00425 QString scsidev = MediaMonitor::defaultCDWriter();
00426 if (scsidev.isEmpty() || scsidev.isNull())
00427 {
00428 VERBOSE(VB_GENERAL, "No CD Writer device defined.");
00429 return;
00430 }
00431
00432
00433 MythProgressDialog *record_progress;
00434 record_progress = new MythProgressDialog(tr("CD-RW Blanking Progress"), 10);
00435
00436
00437 QString blanktype=gContext->GetSetting("CDBlankType");
00438
00439 record_progress->setProgress(1);
00440 strcpy(command,"cdrecord -v ");
00441 strcat(command," dev= ");
00442 strcat(command,scsidev.ascii());
00443 strcat(command," -blank=");
00444 strcat(command,blanktype.ascii());
00445 cout << command << endl;
00446 system(command);
00447
00448 record_progress->Close();
00449 record_progress->deleteLater();
00450 }
00451
00452 void DatabaseBox::deletePlaylist()
00453 {
00454 if (!playlist_popup)
00455 return;
00456
00457
00458
00459 closePlaylistPopup();
00460
00461 UIListGenericTree *item = tree->GetCurrentPosition();
00462
00463 if (TreeCheckItem *check_item = dynamic_cast<TreeCheckItem*>(item) )
00464 {
00465 if (check_item->getID() < 0)
00466 {
00467 if (check_item->nextSibling(1))
00468 tree->MoveDown();
00469 else if (check_item->prevSibling(1))
00470 tree->MoveUp();
00471
00472 gMusicData->all_playlists->deletePlaylist(check_item->getID() * -1);
00473
00474 item->RemoveFromParent();
00475
00476 gMusicData->all_playlists->refreshRelevantPlaylists(alllists);
00477 checkTree();
00478 return;
00479 }
00480 }
00481
00482 VERBOSE(VB_IMPORTANT, "deletePlaylist() - Playlist popup on a "
00483 "non-playlist item");
00484 }
00485
00486
00487 void DatabaseBox::copyToActive()
00488 {
00489 if (!playlist_popup)
00490 return;
00491
00492 closePlaylistPopup();
00493
00494 UIListGenericTree *item = tree->GetCurrentPosition();
00495
00496 if (TreeCheckItem *check_item = dynamic_cast<TreeCheckItem*>(item) )
00497 {
00498 if (check_item->getID() < 0)
00499 {
00500 gMusicData->all_playlists->copyToActive(check_item->getID() * -1);
00501 gMusicData->all_playlists->refreshRelevantPlaylists(alllists);
00502 tree->RefreshCurrentLevel();
00503 checkTree();
00504
00505 return;
00506 }
00507 }
00508 VERBOSE(VB_IMPORTANT, "copyToActive() - Playlist popup on a "
00509 "non-playlist item");
00510 }
00511
00512
00513 void DatabaseBox::fillCD(void)
00514 {
00515 QMutexLocker locker(cd_reader_thread->getLock());
00516
00517 if (cditem)
00518 {
00519
00520
00521
00522 UIListGenericTree *curItem = tree->GetCurrentPosition();
00523 if (dynamic_cast<CDCheckItem*>(curItem))
00524 {
00525 int depth = curItem->calculateDepth(0);
00526 while(depth--)
00527 tree->MoveLeft();
00528 }
00529
00530
00531
00532 while (cditem->childCount())
00533 {
00534 CDCheckItem *track_ptr =
00535 static_cast<CDCheckItem*>(cditem->getChildAt(0));
00536 track_ptr->RemoveFromParent();
00537 }
00538
00539
00540
00541 cditem->setText(gMusicData->all_music->getCDTitle());
00542 cditem->setCheck(0);
00543 cditem->setCheckable(false);
00544
00545 qApp->lock();
00546
00547 gMusicData->all_music->putCDOnTheListView(cditem);
00548
00549
00550
00551 QPtrListIterator<GenericTree> it = cditem->getFirstChildIterator();
00552 UIListGenericTree *uit;
00553
00554 while ((uit = (UIListGenericTree *)it.current()))
00555 {
00556 if (CDCheckItem *track_ptr = dynamic_cast<CDCheckItem*>(uit))
00557 {
00558 track_ptr->setCheck(0);
00559 if (gMusicData->all_playlists->checkCDTrack(track_ptr->getID() * -1))
00560 track_ptr->setCheck(2);
00561 }
00562 ++it;
00563 }
00564
00565 qApp->unlock();
00566
00567
00568
00569 if (cditem->childCount() > 0)
00570 {
00571 cditem->setCheckable(true);
00572 cditem->setCheck(0);
00573 checkParent(cditem);
00574 }
00575
00576 tree->Redraw();
00577 }
00578 }
00579
00580 void DatabaseBox::doMenus(UIListGenericTree *item)
00581 {
00582 if (dynamic_cast<CDCheckItem*>(item))
00583 return;
00584 else if (TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(item))
00585 {
00586 if (item_ptr->getID() < 0)
00587 doPlaylistPopup(item_ptr);
00588 }
00589 else if (PlaylistTitle *item_ptr = dynamic_cast<PlaylistTitle*>(item))
00590 doActivePopup(item_ptr);
00591 }
00592
00593 void DatabaseBox::alternateDoMenus(UIListGenericTree *item, int keypad_number)
00594 {
00595 if (TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(item))
00596 {
00597 bool is_cd = dynamic_cast<CDCheckItem*>(item) != 0;
00598 if (item_ptr->getID() < 0 && !is_cd)
00599 doPlaylistPopup(item_ptr);
00600 else if (item->getParent())
00601 {
00602 int a_number = item->getParent()->childCount();
00603 a_number = (int)(a_number * ( keypad_number / 10.0));
00604
00605 tree->MoveUp(UIListTreeType::MoveMax);
00606 tree->MoveDown(a_number);
00607 }
00608 }
00609 else if (PlaylistTitle *item_ptr = dynamic_cast<PlaylistTitle*>(item))
00610 doActivePopup(item_ptr);
00611 }
00612
00613 void DatabaseBox::entered(UIListTreeType *treetype, UIListGenericTree *item)
00614 {
00615 if (!item || !treetype)
00616 return;
00617
00618
00619 bool cd = false;
00620 if (dynamic_cast<CDCheckItem*>(item))
00621 cd = true;
00622
00623 TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(item);
00624
00625 if (item_ptr
00626 && item->childCount() == 0
00627 && item_ptr->getLevel() == "title")
00628 {
00629 int id = item_ptr->getID();
00630
00631 Metadata *mdata;
00632 if (!cd)
00633 {
00634 mdata = gMusicData->all_music->getMetadata(id);
00635 if (!mdata)
00636 return;
00637 }
00638 else
00639 {
00640
00641 mdata = new Metadata;
00642 if (!gMusicData->all_music->getCDMetadata(id, mdata))
00643 {
00644 delete mdata;
00645 return;
00646 }
00647 }
00648
00649 unsigned int line = 0;
00650 QString tmpstr;
00651
00652 if (mdata->Compilation())
00653 {
00654 tmpstr = tr("Compilation Artist:\t") + mdata->CompilationArtist();
00655 if (m_lines.at(line))
00656 m_lines.at(line++)->SetText(tmpstr);
00657 }
00658
00659 tmpstr = tr("Artist:\t") + mdata->Artist();
00660 if (m_lines.at(line))
00661 m_lines.at(line++)->SetText(tmpstr);
00662
00663 tmpstr = tr("Album:\t") + mdata->Album();
00664 if (m_lines.at(line))
00665 m_lines.at(line++)->SetText(tmpstr);
00666
00667 tmpstr = tr("Title:\t") + mdata->Title();
00668 if (m_lines.at(line))
00669 m_lines.at(line++)->SetText(tmpstr);
00670
00671 if (m_lines.at(line))
00672 {
00673 int maxTime = mdata->Length() / 1000;
00674
00675 int maxh = maxTime / 3600;
00676 int maxm = (maxTime / 60) % 60;
00677 int maxs = maxTime % 60;
00678
00679 QString timeStr;
00680 if (maxh > 0)
00681 timeStr.sprintf("%02d:%02d:%02d", maxh, maxm, maxs);
00682 else
00683 timeStr.sprintf("%02d:%02d", maxm, maxs);
00684
00685 tmpstr = tr("Length:\t") + timeStr;
00686
00687 m_lines.at(line++)->SetText(tmpstr);
00688 }
00689
00690 tmpstr = tr("Genre: ") + mdata->Genre();
00691
00692 if (m_lines.at(line))
00693 {
00694 m_lines.at(line)->SetText(tmpstr);
00695 }
00696 else
00697 {
00698 QString prevvalue = m_lines.at(line-1)->GetText();
00699 tmpstr = prevvalue + " " + tmpstr;
00700 m_lines.at(line-1)->SetText(tmpstr);
00701 }
00702
00703
00704 while (++line < m_lines.count())
00705 m_lines.at(line)->SetText("");
00706
00707
00708 if (cd)
00709 delete mdata;
00710
00711 return;
00712 }
00713
00714 QStringList pathto = treetype->getRouteToCurrent();
00715
00716 int linelen = 0;
00717 int dispat = 0;
00718 QString data = "";
00719
00720 for (QStringList::Iterator it = pathto.begin();
00721 it != pathto.end(); ++it)
00722 {
00723 if (it == pathto.begin())
00724 continue;
00725
00726 if (data != "")
00727 data += " / ";
00728
00729 data += *it;
00730 linelen++;
00731 if (linelen == 2)
00732 {
00733 if (m_lines.at(dispat))
00734 {
00735 m_lines.at(dispat)->SetText(data);
00736 }
00737
00738 data = "";
00739 linelen = 0;
00740 dispat++;
00741 }
00742 }
00743
00744 if (linelen != 0)
00745 {
00746 if (m_lines.at(dispat))
00747 {
00748 m_lines.at(dispat)->SetText(data);
00749 }
00750 dispat++;
00751 }
00752
00753 for (unsigned int i = dispat; i < m_lines.count(); i++)
00754 m_lines.at(i)->SetText("");
00755 }
00756
00757 void DatabaseBox::selected(UIListGenericTree *item)
00758 {
00759 if (!item)
00760 return;
00761
00762 UIListGenericTree *parent = (UIListGenericTree *)item->getParent();
00763
00764 if (CDCheckItem *item_ptr = dynamic_cast<CDCheckItem*>(item))
00765 {
00766
00767 if (active_playlist)
00768 {
00769 if (item_ptr->getCheck() > 0)
00770 item_ptr->setCheck(0);
00771 else
00772 item_ptr->setCheck(2);
00773 doSelected(item_ptr, true);
00774 if (CDCheckItem *item_ptr = dynamic_cast<CDCheckItem*>(parent))
00775 checkParent(item_ptr);
00776 tree->Redraw();
00777 }
00778
00779 }
00780 else if (TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(item))
00781 {
00782 if (active_playlist)
00783 {
00784 if (item_ptr->getCheck() > 0)
00785 item_ptr->setCheck(0);
00786 else
00787 item_ptr->setCheck(2);
00788 doSelected(item_ptr, false);
00789 if (TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(parent))
00790 checkParent(item_ptr);
00791 tree->Redraw();
00792 }
00793 }
00794 else if (PlaylistItem *item_ptr = dynamic_cast<PlaylistTrack*>(item))
00795 dealWithTracks(item_ptr);
00796 else if (PlaylistTitle *item_ptr = dynamic_cast<PlaylistTitle*>(item))
00797 doActivePopup(item_ptr);
00798 else
00799 {
00800 VERBOSE(VB_IMPORTANT, "That's odd ... there's something I don't "
00801 "recognize on a ListView");
00802 }
00803 }
00804
00805
00806 void DatabaseBox::doPlaylistPopup(TreeCheckItem *item_ptr)
00807 {
00808 if (playlist_popup)
00809 return;
00810
00811
00812 playlist_popup = new MythPopupBox(gContext->GetMainWindow(),
00813 "playlist_popup");
00814
00815 QButton *mac_b = playlist_popup->addButton(tr("Move to Active Play Queue"),
00816 this, SLOT(copyToActive()));
00817
00818 playlist_popup->addButton(tr("Delete This Playlist"), this,
00819 SLOT(deletePlaylist()));
00820
00821 playlist_rename = new MythRemoteLineEdit(playlist_popup);
00822 playlist_rename->setText(item_ptr->getString());
00823 playlist_popup->addWidget(playlist_rename);
00824
00825 playlist_popup->addButton(tr("Rename This Playlist"), this,
00826 SLOT(renamePlaylist()));
00827
00828 playlist_popup->ShowPopup(this, SLOT(closePlaylistPopup()));
00829
00830 mac_b->setFocus();
00831 }
00832
00833 void DatabaseBox::closePlaylistPopup(void)
00834 {
00835 if (!playlist_popup)
00836 return;
00837
00838 playlist_popup->hide();
00839 playlist_popup->deleteLater();
00840 playlist_popup = NULL;
00841 }
00842
00843 void DatabaseBox::doActivePopup(PlaylistTitle *item_ptr)
00844 {
00845 if (active_popup)
00846 return;
00847
00848
00849 active_popup = new MythPopupBox(gContext->GetMainWindow(),
00850 "active_popup");
00851 active_pl_edit = new MythRemoteLineEdit(active_popup);
00852 active_popup->addWidget(active_pl_edit);
00853 active_pl_edit->setFocus();
00854
00855 active_popup->addButton(tr("Copy To New Playlist"), this,
00856 SLOT(copyNewPlaylist()));
00857
00858 active_popup->addButton(tr("Clear the Active Play Queue"), this,
00859 SLOT(clearActive()));
00860
00861 QButton *pb = active_popup->addButton(tr("Save Back to Playlist Tree"),
00862 this, SLOT(popBackPlaylist()));
00863
00864
00865
00866 bool cdwriter = false;
00867
00868 if (gContext->GetNumSetting("CDWriterEnabled"))
00869 {
00870 QString scsidev = gContext->GetSetting("CDWriterDevice");
00871 if (!scsidev.isEmpty() && !scsidev.isNull())
00872 cdwriter = true;
00873 }
00874
00875 QButton *cdaudiob = NULL;
00876 QButton *cdmp3b = NULL;
00877
00878 if (cdwriter)
00879 {
00880 #if 0
00881
00882
00883
00884
00885 cdaudiob = active_popup->addButton(tr("Create Audio CD from "
00886 "Playlist"), this,
00887 SLOT(CreateCDAudio()));
00888 #endif
00889
00890 cdmp3b = active_popup->addButton(tr("Create MP3 CD from Playlist"),
00891 this, SLOT(CreateCDMP3()));
00892
00893 active_popup->addButton(tr("Clear CD-RW Disk"), this,
00894 SLOT(BlankCDRW()));
00895
00896 double size_in_MB = 0.0;
00897 double size_in_sec = 0.0;
00898 active_playlist->computeSize(size_in_MB, size_in_sec);
00899
00900 int disksize = gContext->GetNumSetting("CDDiskSize", 2);
00901
00902 double max_size_in_MB;
00903 double max_size_in_min;
00904
00905 if (disksize == 1)
00906 {
00907 max_size_in_MB = 650;
00908 max_size_in_min = 75;
00909 }
00910 else
00911 {
00912 max_size_in_MB = 700;
00913 max_size_in_min = 80;
00914 }
00915
00916 double ratio_MB = 100.0 * size_in_MB / max_size_in_MB;
00917 double ratio_sec = 100.0 * size_in_sec / 60.0 / 1000.0 / max_size_in_min;
00918
00919 QString label1;
00920 QString label2;
00921
00922 label1.sprintf("Size: %dMB (%02d%%)", (int)(size_in_MB),
00923 (int)(ratio_MB));
00924 label2.sprintf("Duration: %3dmin (%02d%%)",
00925 (int)(size_in_sec / 60.0 / 1000.0), (int)(ratio_sec));
00926
00927 active_popup->addLabel(label1);
00928 active_popup->addLabel(label2);
00929
00930 cdmp3b->setEnabled((ratio_MB <= 100.0));
00931
00932 if (cdaudiob)
00933 {
00934 cdaudiob->setEnabled((ratio_sec <= 100.0));
00935 cdaudiob->setEnabled(false);
00936 }
00937 }
00938
00939 (void)item_ptr;
00940
00941 active_pl_edit->setText("");
00942
00943 active_popup->ShowPopup(this, SLOT(closeActivePopup()));
00944
00945 if (gMusicData->all_playlists->pendingWriteback())
00946 pb->setEnabled(true);
00947 else
00948 pb->setEnabled(false);
00949 }
00950
00951 void DatabaseBox::closeActivePopup(void)
00952 {
00953 if (!active_popup)
00954 return;
00955
00956 active_popup->hide();
00957 active_popup->deleteLater();
00958 active_popup = NULL;
00959 }
00960
00961 void DatabaseBox::dealWithTracks(PlaylistItem *item_ptr)
00962 {
00963
00964
00965 if (holding_track)
00966 {
00967 VERBOSE(VB_IMPORTANT, "dealWithTracks() - Holding track. This is not "
00968 "supposed to happen");
00969 holding_track = false;
00970 track_held->beMoving(false);
00971 releaseKeyboard();
00972 tree->RedrawCurrent();
00973 }
00974 else
00975 {
00976 holding_track = true;
00977 track_held = dynamic_cast<PlaylistTrack*>(item_ptr);
00978 track_held->beMoving(true);
00979 grabKeyboard();
00980 tree->RedrawCurrent();
00981 }
00982 }
00983
00984 void DatabaseBox::doSelected(UIListGenericTree *item, bool cd_flag)
00985 {
00986 bool keep_going = false;
00987
00988 TreeCheckItem *tcitem = (TreeCheckItem *)item;
00989
00990 if (tcitem->childCount() > 0)
00991 {
00992 keep_going = true;
00993 UIListGenericTree *test = (UIListGenericTree *)tcitem->getChildAt(0);
00994 if (PlaylistItem *check_item = dynamic_cast<PlaylistItem*>(test))
00995 {
00996 (void)check_item;
00997 keep_going = false;
00998 }
00999 }
01000
01001 if (keep_going)
01002 {
01003 QPtrListIterator<GenericTree> it = tcitem->getFirstChildIterator();
01004 TreeCheckItem *child;
01005 while ((child = (TreeCheckItem *)it.current()))
01006 {
01007 if (child->getCheck() != tcitem->getCheck())
01008 {
01009 child->setCheck(tcitem->getCheck());
01010 doSelected(child, cd_flag);
01011 }
01012 ++it;
01013 }
01014 }
01015 else
01016 {
01017 if (tcitem->getCheck() == 2)
01018 active_playlist->addTrack(tcitem->getID(), true, cd_flag);
01019 else
01020 active_playlist->removeTrack(tcitem->getID(), cd_flag);
01021 }
01022 }
01023
01024 void DatabaseBox::checkParent(UIListGenericTree *item)
01025 {
01026 if (!item)
01027 return;
01028
01029 bool do_check = false;
01030
01031 if (TreeCheckItem *tcitem = dynamic_cast<TreeCheckItem*>(item))
01032 {
01033 (void)tcitem;
01034 do_check = true;
01035 }
01036 else if (CDCheckItem *tcitem = dynamic_cast<CDCheckItem*>(item))
01037 {
01038 (void)tcitem;
01039 do_check = true;
01040 }
01041
01042 if (do_check)
01043 {
01044 TreeCheckItem *tcitem = dynamic_cast<TreeCheckItem*>(item);
01045 TreeCheckItem *child = (TreeCheckItem *)tcitem->getChildAt(0);
01046 if (!child)
01047 return;
01048
01049 bool allon = true;
01050 bool oneon = false;
01051
01052 QPtrListIterator<GenericTree> it = tcitem->getFirstChildIterator();
01053
01054 while ((child = (TreeCheckItem *)it.current()))
01055 {
01056 if (child->getCheck() > 0)
01057 oneon = true;
01058 if (child->getCheck() == 0)
01059 allon = false;
01060
01061 ++it;
01062 }
01063
01064 if (allon)
01065 tcitem->setCheck(2);
01066 else if (oneon)
01067 tcitem->setCheck(1);
01068 else
01069 tcitem->setCheck(0);
01070
01071 if (tcitem->getParent())
01072 checkParent((UIListGenericTree *)tcitem->getParent());
01073 }
01074 }
01075
01076 void DatabaseBox::deleteTrack(UIListGenericTree *item)
01077 {
01078 if (PlaylistTrack *delete_item = dynamic_cast<PlaylistCD*>(item) )
01079 {
01080 if (delete_item->nextSibling(1))
01081 tree->MoveDown();
01082 else if (delete_item->prevSibling(1))
01083 tree->MoveUp();
01084
01085 UIListGenericTree *item = (UIListGenericTree *)delete_item->getParent();
01086 if (TreeCheckItem *item_owner = dynamic_cast<TreeCheckItem*>(item))
01087 {
01088 Playlist *owner = gMusicData->all_playlists->getPlaylist(item_owner->getID() *
01089 -1);
01090 owner->removeTrack(delete_item->getID(), true);
01091 }
01092 else if (PlaylistTitle *item_owner = dynamic_cast<PlaylistTitle*>(item))
01093 {
01094 (void)item_owner;
01095 active_playlist->removeTrack(delete_item->getID(), true);
01096 }
01097 else
01098 {
01099 VERBOSE(VB_IMPORTANT, "deleteTrack() - I don't know how to delete "
01100 "whatever you're trying to get rid of");
01101 }
01102
01103 gMusicData->all_playlists->refreshRelevantPlaylists(alllists);
01104 checkTree();
01105 }
01106 else if (PlaylistTrack *delete_item = dynamic_cast<PlaylistTrack*>(item))
01107 {
01108 if (delete_item->nextSibling(1))
01109 tree->MoveDown();
01110 else if (delete_item->prevSibling(1))
01111 tree->MoveUp();
01112
01113 UIListGenericTree *item = (UIListGenericTree *)delete_item->getParent();
01114 if (TreeCheckItem *item_owner = dynamic_cast<TreeCheckItem*>(item))
01115 {
01116 Playlist *owner = gMusicData->all_playlists->getPlaylist(item_owner->getID() *
01117 -1);
01118 owner->removeTrack(delete_item->getID(), false);
01119 }
01120 else if (PlaylistTitle *item_owner = dynamic_cast<PlaylistTitle*>(item))
01121 {
01122 (void)item_owner;
01123 active_playlist->removeTrack(delete_item->getID(), false);
01124 }
01125 else
01126 {
01127 VERBOSE(VB_IMPORTANT, "deleteTrack() - I don't know how to delete "
01128 "whatever you're trying to get rid of");
01129 }
01130 gMusicData->all_playlists->refreshRelevantPlaylists(alllists);
01131 checkTree();
01132 }
01133 }
01134
01135 void DatabaseBox::moveHeldUpDown(bool flag)
01136 {
01137 track_held->moveUpDown(flag);
01138 tree->RedrawCurrent();
01139
01140
01141 }
01142
01143 void DatabaseBox::keyPressEvent(QKeyEvent *e)
01144 {
01145
01146
01147 if (holding_track)
01148 {
01149 bool handled = false;
01150 QStringList actions;
01151 gContext->GetMainWindow()->TranslateKeyPress("Qt", e, actions);
01152 for (unsigned int i = 0; i < actions.size() && !handled; i++)
01153 {
01154 QString action = actions[i];
01155 handled = true;
01156
01157 if (action == "SELECT" || action == "ESCAPE")
01158 {
01159
01160 holding_track = false;
01161 track_held->beMoving(false);
01162 tree->RedrawCurrent();
01163 releaseKeyboard();
01164 }
01165 else if (action == "UP")
01166 moveHeldUpDown(true);
01167 else if (action == "DOWN")
01168 moveHeldUpDown(false);
01169 else
01170 handled = false;
01171 }
01172 return;
01173 }
01174
01175 bool handled = false;
01176 QStringList actions;
01177 gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions);
01178
01179 UIListGenericTree *curItem = tree->GetCurrentPosition();
01180
01181 for (unsigned int i = 0; i < actions.size() && !handled; i++)
01182 {
01183 QString action = actions[i];
01184 handled = true;
01185
01186 if (action == "DELETE")
01187 deleteTrack(curItem);
01188 else if (action == "MENU" || action == "INFO")
01189 doMenus(curItem);
01190 else if (action == "SELECT")
01191 selected(curItem);
01192 else if (action == "0" || action == "1" || action == "2" ||
01193 action == "3" || action == "4" || action == "5" ||
01194 action == "6" || action == "7" || action == "8" ||
01195 action == "9")
01196 {
01197 alternateDoMenus(curItem, action.toInt());
01198 }
01199 else if (action == "UP")
01200 tree->MoveUp();
01201 else if (action == "DOWN")
01202 tree->MoveDown();
01203 else if (action == "LEFT")
01204 tree->MoveLeft();
01205 else if (action == "RIGHT")
01206 tree->MoveRight();
01207 else if (action == "PAGEUP")
01208 tree->MoveUp(UIListTreeType::MovePage);
01209 else if (action == "PAGEDOWN")
01210 tree->MoveDown(UIListTreeType::MovePage);
01211 else if (action == "INCSEARCH")
01212 tree->incSearchStart();
01213 else if (action == "INCSEARCHNEXT")
01214 tree->incSearchNext();
01215 else
01216 handled = false;
01217 }
01218
01219 if (handled)
01220 return;
01221
01222 MythDialog::keyPressEvent(e);
01223 }
01224
01225 void DatabaseBox::checkTree(UIListGenericTree *startingpoint)
01226 {
01227 bool toplevel = false;
01228 if (!startingpoint)
01229 {
01230 toplevel = true;
01231 startingpoint = rootNode;
01232 }
01233
01234 QPtrListIterator<GenericTree> it = startingpoint->getFirstChildIterator();
01235 UIListGenericTree *uit;
01236
01237
01238
01239
01240 while ((uit = (UIListGenericTree *)it.current()))
01241 {
01242
01243 if (TreeCheckItem *item = dynamic_cast<TreeCheckItem*>(uit))
01244 {
01245 bool is_cd = dynamic_cast<CDCheckItem*>(uit) != 0;
01246 item->setCheck(0);
01247 if (active_playlist->checkTrack(item->getID(), is_cd))
01248 {
01249
01250 item->setCheck(2);
01251 checkParent((UIListGenericTree *)item->getParent());
01252 }
01253
01254 if (item->childCount() > 0)
01255 checkTree(item);
01256 }
01257
01258 ++it;
01259 }
01260
01261 if (toplevel)
01262 tree->Redraw();
01263 }
01264
01265 void DatabaseBox::setCDTitle(const QString& title)
01266 {
01267 if (cditem)
01268 cditem->setText(title);
01269 }
01270
01271 ReadCDThread::ReadCDThread(const QString &dev)
01272 {
01273 m_CDdevice = dev;
01274 cd_status_changed = false;
01275 }
01276
01277 void ReadCDThread::run()
01278 {
01279 #ifndef USING_MINGW
01280
01281 QMutexLocker locker(getLock());
01282
01283 CdDecoder *decoder = new CdDecoder("cda", NULL, NULL, NULL);
01284 decoder->setDevice(m_CDdevice);
01285 int tracknum = decoder->getNumCDAudioTracks();
01286
01287 bool redo = false;
01288
01289 if (tracknum != gMusicData->all_music->getCDTrackCount())
01290 {
01291 cd_status_changed = true;
01292 VERBOSE(VB_IMPORTANT, QString("CD status has changed."));
01293 }
01294 else
01295 cd_status_changed = false;
01296
01297 if (tracknum == 0)
01298 {
01299
01300 gMusicData->all_music->clearCDData();
01301 gMusicData->all_playlists->clearCDList();
01302 }
01303 else if (tracknum > 0)
01304 {
01305
01306
01307 Metadata *checker = decoder->getLastMetadata();
01308 if (checker)
01309 {
01310 if (!gMusicData->all_music->checkCDTrack(checker))
01311 {
01312 redo = true;
01313 cd_status_changed = true;
01314 gMusicData->all_music->clearCDData();
01315 gMusicData->all_playlists->clearCDList();
01316 }
01317 else
01318 cd_status_changed = false;
01319 delete checker;
01320 }
01321 else
01322 {
01323 VERBOSE(VB_IMPORTANT, "The cddecoder said it had audio tracks, "
01324 "but it won't tell me about them");
01325 }
01326 }
01327
01328 int tracks = decoder->getNumTracks();
01329 bool setTitle = false;
01330
01331 for (int actual_tracknum = 1;
01332 redo && actual_tracknum <= tracks; actual_tracknum++)
01333 {
01334 Metadata *track = decoder->getMetadata(actual_tracknum);
01335 if (track)
01336 {
01337 gMusicData->all_music->addCDTrack(track);
01338
01339 if (!setTitle)
01340 {
01341
01342 QString parenttitle = " ";
01343 if (track->FormatArtist().length() > 0)
01344 {
01345 parenttitle += track->FormatArtist();
01346 parenttitle += " ~ ";
01347 }
01348
01349 if (track->Album().length() > 0)
01350 parenttitle += track->Album();
01351 else
01352 {
01353 parenttitle = " " + QObject::tr("Unknown");
01354 VERBOSE(VB_GENERAL, "Couldn't find your "
01355 " CD. It may not be in the freedb database.\n"
01356 " More likely, however, is that you need to delete\n"
01357 " ~/.cddb and ~/.cdserverrc and restart mythmusic.");
01358 }
01359 gMusicData->all_music->setCDTitle(parenttitle);
01360 setTitle = true;
01361 }
01362 delete track;
01363 }
01364 }
01365
01366 delete decoder;
01367 #endif // USING_MINGW
01368 }
01369