Changeset 176 for smplayer/trunk/src/playlist.cpp
- Timestamp:
- May 3, 2016, 5:25:45 PM (9 years ago)
- Location:
- smplayer/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
smplayer/trunk
- Property svn:mergeinfo changed
/smplayer/vendor/current merged: 175
- Property svn:mergeinfo changed
-
smplayer/trunk/src/playlist.cpp
r170 r176 1 1 /* smplayer, GUI front-end for mplayer. 2 Copyright (C) 2006-201 4Ricardo Villalba <rvm@users.sourceforge.net>2 Copyright (C) 2006-2016 Ricardo Villalba <rvm@users.sourceforge.net> 3 3 4 4 This program is free software; you can redistribute it and/or modify … … 41 41 #include <QApplication> 42 42 #include <QMimeData> 43 #include <QDomDocument> 44 #include <QDebug> 43 45 44 46 #include "mytablewidget.h" … … 62 64 63 65 #define DRAG_ITEMS 0 66 #define PL_ALLOW_DUPLICATES 1 64 67 65 68 #define COL_PLAY 0 … … 79 82 80 83 automatically_play_next = true; 84 ignore_player_errors = false; 81 85 82 86 row_spacing = -1; // Default height … … 93 97 94 98 connect( core, SIGNAL(mediaFinished()), this, SLOT(playNext()), Qt::QueuedConnection ); 99 connect( core, SIGNAL(mplayerFailed(QProcess::ProcessError)), this, SLOT(playerFailed(QProcess::ProcessError)) ); 100 connect( core, SIGNAL(mplayerFinishedWithError(int)), this, SLOT(playerFinishedWithError(int)) ); 95 101 connect( core, SIGNAL(mediaLoaded()), this, SLOT(getMediaInfo()) ); 96 102 … … 236 242 editAct = new MyAction(this, "pl_edit", false); 237 243 connect( editAct, SIGNAL(triggered()), this, SLOT(editCurrentItem()) ); 244 245 deleteSelectedFileFromDiskAct = new MyAction(this, "pl_delete_from_disk"); 246 connect( deleteSelectedFileFromDiskAct, SIGNAL(triggered()), this, SLOT(deleteSelectedFileFromDisk())); 238 247 } 239 248 … … 284 293 popup->addAction(removeSelectedAct); 285 294 popup->addAction(editAct); 295 popup->addAction(deleteSelectedFileFromDiskAct); 286 296 287 297 connect( listView, SIGNAL(customContextMenuRequested(const QPoint &)), … … 320 330 removeSelectedAct->change( tr("Remove &selected") ); 321 331 removeAllAct->change( tr("Remove &all") ); 332 333 deleteSelectedFileFromDiskAct->change( tr("&Delete file from disk") ); 322 334 323 335 // Edit … … 456 468 #endif 457 469 470 #if !PL_ALLOW_DUPLICATES 458 471 // Test if already is in the list 459 472 bool exists = false; … … 474 487 475 488 if (!exists) { 489 #endif 476 490 if (name.isEmpty()) { 477 491 QFileInfo fi(filename); … … 487 501 pl.append( PlaylistItem(filename, name, duration) ); 488 502 //setModified( true ); // Better set the modified on a higher level 503 #if !PL_ALLOW_DUPLICATES 489 504 } else { 490 505 qDebug("Playlist::addItem: item not added, already in the list"); 491 506 } 507 #endif 492 508 } 493 509 … … 591 607 QRegExp info("^#EXTINF:(.*),(.*)"); 592 608 593 594 609 QFile f( file ); 610 if ( f.open( QIODevice::ReadOnly ) ) { 595 611 playlist_path = QFileInfo(file).path(); 596 612 … … 600 616 double duration=0; 601 617 602 618 QTextStream stream( &f ); 603 619 604 620 if (utf8) … … 607 623 stream.setCodec(QTextCodec::codecForLocale()); 608 624 609 QString line; 610 while ( !stream.atEnd() ) { 611 line = stream.readLine(); // line of text excluding '\n' 612 qDebug( " * line: '%s'", line.toUtf8().data() ); 625 QString line; 626 while ( !stream.atEnd() ) { 627 line = stream.readLine().trimmed(); 628 if (line.isEmpty()) continue; // Ignore empty lines 629 630 qDebug( "Playlist::load_m3u: line: '%s'", line.toUtf8().data() ); 613 631 if (m3u_id.indexIn(line)!=-1) { 614 632 //#EXTM3U … … 619 637 duration = info.cap(1).toDouble(); 620 638 name = info.cap(2); 621 qDebug(" *name: '%s', duration: %f", name.toUtf8().data(), duration );639 qDebug("Playlist::load_m3u: name: '%s', duration: %f", name.toUtf8().data(), duration ); 622 640 } 623 641 else … … 640 658 duration = 0; 641 659 } 642 643 660 } 661 f.close(); 644 662 list(); 645 663 updateView(); … … 698 716 699 717 if (set.status() == QSettings::NoError) startPlay(); 718 } 719 720 void Playlist::loadXSPF(const QString & filename) { 721 qDebug() << "Playlist::loadXSPF:" << filename; 722 723 QFile f(filename); 724 if (!f.open(QIODevice::ReadOnly)) { 725 return; 726 } 727 728 QDomDocument dom_document; 729 bool ok = dom_document.setContent(f.readAll()); 730 qDebug() << "Playlist::loadXSPF: success:" << ok; 731 if (!ok) return; 732 733 QDomNode root = dom_document.documentElement(); 734 qDebug() << "Playlist::loadXSPF: tagname:" << root.toElement().tagName(); 735 736 QDomNode child = root.firstChildElement("trackList"); 737 if (!child.isNull()) { 738 clear(); 739 740 qDebug() << "Playlist::loadXSPF: child:" << child.nodeName(); 741 QDomNode track = child.firstChildElement("track"); 742 while (!track.isNull()) { 743 QString location = QUrl::fromPercentEncoding(track.firstChildElement("location").text().toLatin1()); 744 QString title = track.firstChildElement("title").text(); 745 int duration = track.firstChildElement("duration").text().toInt(); 746 747 qDebug() << "Playlist::loadXSPF: location:" << location; 748 qDebug() << "Playlist::loadXSPF: title:" << title; 749 qDebug() << "Playlist::loadXSPF: duration:" << duration; 750 751 addItem( location, title, (double) duration / 1000 ); 752 753 track = track.nextSiblingElement("track"); 754 } 755 756 list(); 757 updateView(); 758 setModified( false ); 759 startPlay(); 760 } 700 761 } 701 762 … … 800 861 } 801 862 863 bool Playlist::saveXSPF(const QString & filename) { 864 qDebug() << "Playlist::saveXSPF:" << filename; 865 866 QFile f(filename); 867 if (f.open( QIODevice::WriteOnly)) { 868 QTextStream stream(&f); 869 stream.setCodec("UTF-8"); 870 871 stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 872 stream << "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n"; 873 stream << "\t<trackList>\n"; 874 875 for ( int n=0; n < pl.count(); n++ ) { 876 QString location = pl[n].filename(); 877 qDebug() << "Playlist::saveXSPF:" << location; 878 879 bool is_local = QFile::exists(location); 880 881 #ifdef Q_OS_WIN 882 if (is_local) { 883 location.replace("\\", "/"); 884 } 885 #endif 886 //qDebug() << "Playlist::saveXSPF:" << location; 887 888 QUrl url(location); 889 location = url.toEncoded(); 890 //qDebug() << "Playlist::saveXSPF:" << location; 891 892 if (!location.startsWith("file:") && is_local) { 893 #ifdef Q_OS_WIN 894 location = "file:///" + location; 895 #else 896 location = "file://" + location; 897 #endif 898 } 899 900 QString title = pl[n].name(); 901 int duration = pl[n].duration() * 1000; 902 903 #if QT_VERSION >= 0x050000 904 location = location.toHtmlEscaped(); 905 title = title.toHtmlEscaped(); 906 #else 907 location = Qt::escape(location); 908 title = Qt::escape(title); 909 #endif 910 911 stream << "\t\t<track>\n"; 912 stream << "\t\t\t<location>" << location << "</location>\n"; 913 stream << "\t\t\t<title>" << title << "</title>\n"; 914 stream << "\t\t\t<duration>" << duration << "</duration>\n"; 915 stream << "\t\t</track>\n"; 916 } 917 918 stream << "\t</trackList>\n"; 919 stream << "</playlist>\n"; 920 921 setModified(false); 922 return true; 923 } else { 924 return false; 925 } 926 } 927 802 928 803 929 void Playlist::load() { … … 807 933 this, tr("Choose a file"), 808 934 lastDir(), 809 tr("Playlists") + e.playlist().forFilter() );935 tr("Playlists") + e.playlist().forFilter() + ";;" + tr("All files") +" (*)"); 810 936 811 937 if (!s.isEmpty()) { 812 938 latest_dir = QFileInfo(s).absolutePath(); 813 939 814 if (QFileInfo(s).suffix().toLower() == "pls") 940 QString suffix = QFileInfo(s).suffix().toLower(); 941 if (suffix == "pls") { 815 942 load_pls(s); 943 } 816 944 else 945 if (suffix == "xspf") { 946 loadXSPF(s); 947 } 948 else { 817 949 load_m3u(s); 950 } 818 951 } 819 952 } … … 825 958 this, tr("Choose a filename"), 826 959 lastDir(), 827 tr("Playlists") + e.playlist().forFilter() );960 tr("Playlists") + e.playlist().forFilter() + ";;" + tr("All files") +" (*)"); 828 961 829 962 if (!s.isEmpty()) { … … 846 979 latest_dir = QFileInfo(s).absolutePath(); 847 980 848 if (QFileInfo(s).suffix().toLower() == "pls") 981 QString suffix = QFileInfo(s).suffix().toLower(); 982 if (suffix == "pls") { 849 983 return save_pls(s); 984 } 850 985 else 986 if (suffix == "xspf") { 987 return saveXSPF(s); 988 } 989 else { 851 990 return save_m3u(s); 991 } 852 992 853 993 } else { … … 933 1073 // Shuffle 934 1074 int chosen_item = chooseRandomItem(); 1075 qDebug("Playlist::playNext: chosen_item: %d", chosen_item); 935 1076 if (chosen_item == -1) { 936 1077 clearPlayedTag(); 937 if (repeatAct->isChecked()) chosen_item = chooseRandomItem(); 1078 if (repeatAct->isChecked()) { 1079 chosen_item = chooseRandomItem(); 1080 if (chosen_item == -1) chosen_item = 0; 1081 } 938 1082 } 939 1083 playItem( chosen_item ); … … 968 1112 969 1113 void Playlist::getMediaInfo() { 970 qDebug("Playlist:: 1114 qDebug("Playlist::getMediaInfo"); 971 1115 972 1116 QString filename = core->mdat.filename; … … 993 1137 if (!artist.isEmpty()) name = artist + " - " + name; 994 1138 995 int pos=0; 996 PlaylistItemList::iterator it; 997 for ( it = pl.begin(); it != pl.end(); ++it ) { 998 /* qDebug("Playlist:: getMediaInfo: f1: %s f2: %s", (*it).filename().toUtf8().constData(), filename.toUtf8().constData()); */ 999 if ( (*it).filename() == filename ) { 1000 /* qDebug("Playlist:: getMediaInfo: duration: %f", (*it).duration()); */ 1001 if ((*it).duration()<1) { 1139 for (int n = 0; n < pl.count(); n++) { 1140 if (pl[n].filename() == filename) { 1141 // Found item 1142 if (pl[n].duration() < 1) { 1002 1143 if (!name.isEmpty()) { 1003 (*it).setName(name);1144 pl[n].setName(name); 1004 1145 } 1005 (*it).setDuration(duration); 1006 //setModified( true ); 1007 } 1008 else 1146 pl[n].setDuration(duration); 1147 } 1148 else 1009 1149 // Edited name (sets duration to 1) 1010 if ((*it).duration()==1) { 1011 (*it).setDuration(duration); 1012 //setModified( true ); 1013 } 1014 setCurrentItem(pos); 1015 } 1016 pos++; 1017 } 1150 if (pl[n].duration() == 1) { 1151 pl[n].setDuration(duration); 1152 } 1153 } 1154 } 1155 1018 1156 updateView(); 1019 1157 } … … 1052 1190 #endif 1053 1191 1054 QStringList::Iterator it = files.begin(); 1055 while( it != files.end() ) { 1192 QString initial_file; 1193 if (pl.count() == 1) initial_file = pl[0].filename(); 1194 int new_current_item = -1; 1195 1196 for (int n = 0; n < files.count(); n++) { 1197 QString name = ""; 1198 double duration = 0; 1056 1199 #if USE_INFOPROVIDER 1057 if ( (get_info) && (QFile::exists((*it))) ) { 1058 data = InfoProvider::getInfo( (*it) ); 1059 addItem( (*it), data.displayName(), data.duration ); 1200 if ( (get_info) && (QFile::exists(files[n])) ) { 1201 data = InfoProvider::getInfo(files[n]); 1202 name = data.displayName(); 1203 duration = data.duration; 1060 1204 //updateView(); 1061 1205 //qApp->processEvents(); 1062 } else { 1063 addItem( (*it), "", 0 ); 1064 } 1065 #else 1066 addItem( (*it), "", 0 ); 1206 } 1067 1207 #endif 1068 1208 1069 if (QFile::exists(*it)) { 1070 latest_dir = QFileInfo((*it)).absolutePath(); 1071 } 1072 1073 ++it; 1074 } 1209 //qDebug() << "Playlist::addFiles: comparing:" << initial_file << "with" << files[n]; 1210 1211 if (!initial_file.isEmpty() && files[n] == initial_file) { 1212 PlaylistItem first_item = pl.takeFirst(); 1213 name = first_item.name(); 1214 duration = first_item.duration(); 1215 new_current_item = n; 1216 } 1217 addItem(files[n], name, duration); 1218 1219 if (QFile::exists(files[n])) { 1220 latest_dir = QFileInfo(files[n]).absolutePath(); 1221 } 1222 } 1075 1223 #if USE_INFOPROVIDER 1076 1224 unsetCursor(); 1077 1225 #endif 1226 1227 if (new_current_item != -1) setCurrentItem(new_current_item); 1078 1228 updateView(); 1079 1229 … … 1201 1351 1202 1352 void Playlist::clearPlayedTag() { 1203 PlaylistItemList::iterator it; 1204 for ( it = pl.begin(); it != pl.end(); ++it ) { 1205 (*it).setPlayed(false); 1353 for (int n = 0; n < pl.count(); n++) { 1354 pl[n].setPlayed(false); 1206 1355 } 1207 1356 updateView(); … … 1210 1359 int Playlist::chooseRandomItem() { 1211 1360 qDebug( "Playlist::chooseRandomItem"); 1361 1212 1362 QList <int> fi; //List of not played items (free items) 1213 1214 int n=0; 1215 PlaylistItemList::iterator it; 1216 for ( it = pl.begin(); it != pl.end(); ++it ) { 1217 if (! (*it).played() ) fi.append(n); 1218 n++; 1219 } 1220 1221 qDebug(" * free items: %d", fi.count() ); 1222 1223 if (fi.count()==0) return -1; // none free 1224 1225 qDebug(" * items: "); 1226 for (int i=0; i < fi.count(); i++) { 1227 qDebug(" * item: %d", fi[i]); 1363 for (int n = 0; n < pl.count(); n++) { 1364 if (!pl[n].played()) fi.append(n); 1365 } 1366 1367 qDebug("Playlist::chooseRandomItem: free items: %d", fi.count() ); 1368 1369 if (fi.count() == 0) return -1; // none free 1370 1371 qDebug("Playlist::chooseRandomItem: items: "); 1372 for (int i = 0; i < fi.count(); i++) { 1373 qDebug("Playlist::chooseRandomItem: * item: %d", fi[i]); 1228 1374 } 1229 1375 1230 1376 int selected = (int) ((double) fi.count() * rand()/(RAND_MAX+1.0)); 1231 qDebug(" *selected item: %d (%d)", selected, fi[selected]);1377 qDebug("Playlist::chooseRandomItem: selected item: %d (%d)", selected, fi[selected]); 1232 1378 return fi[selected]; 1233 1379 } … … 1312 1458 setModified( true ); 1313 1459 } 1460 } 1461 1462 void Playlist::deleteSelectedFileFromDisk() { 1463 qDebug("Playlist::deleteSelectedFileFromDisk"); 1464 1465 int current = listView->currentRow(); 1466 if (current > -1) { 1467 // If more that one row is selected, select only the current one 1468 listView->clearSelection(); 1469 listView->setCurrentCell(current, 0); 1470 1471 QString filename = pl[current].filename(); 1472 qDebug() << "Playlist::deleteSelectedFileFromDisk: current file:" << filename; 1473 1474 QFileInfo fi(filename); 1475 if (fi.exists() && fi.isFile() && fi.isWritable()) { 1476 // Ask the user for confirmation 1477 int res = QMessageBox::question(this, tr("Confirm deletion"), 1478 tr("You're about to DELETE the file '%1' from your drive.").arg(filename) + "<br>"+ 1479 tr("This action cannot be undone. Are you sure you want to proceed?"), 1480 QMessageBox::Yes, QMessageBox::No); 1481 1482 if (res == QMessageBox::Yes) { 1483 // Delete file 1484 bool success = QFile::remove(filename); 1485 //bool success = false; 1486 1487 if (success) { 1488 // Remove item from the playlist 1489 removeSelected(); 1490 } else { 1491 QMessageBox::warning(this, tr("Deletion failed"), 1492 tr("It wasn't possible to delete '%1'").arg(filename)); 1493 } 1494 } 1495 } else { 1496 qDebug("Playlist::deleteSelectedFileFromDisk: file doesn't exists, it's not a file or it's not writable"); 1497 QMessageBox::information(this, tr("Error deleting the file"), 1498 tr("It's not possible to delete '%1' from the filesystem.").arg(filename)); 1499 } 1500 } 1314 1501 } 1315 1502 … … 1378 1565 } 1379 1566 1567 void Playlist::playerFailed(QProcess::ProcessError e) { 1568 qDebug("Playlist::playerFailed"); 1569 if (ignore_player_errors) { 1570 if (e != QProcess::FailedToStart) { 1571 playNext(); 1572 } 1573 } 1574 } 1575 1576 void Playlist::playerFinishedWithError(int e) { 1577 qDebug("Playlist::playerFinishedWithError: %d", e); 1578 if (ignore_player_errors) { 1579 playNext(); 1580 } 1581 } 1380 1582 1381 1583 void Playlist::maybeSaveSettings() { … … 1403 1605 set->setValue( "play_files_from_start", play_files_from_start ); 1404 1606 set->setValue( "automatically_play_next", automatically_play_next ); 1607 set->setValue( "ignore_player_errors", ignore_player_errors ); 1405 1608 1406 1609 set->setValue( "row_spacing", row_spacing ); … … 1449 1652 play_files_from_start = set->value( "play_files_from_start", play_files_from_start ).toBool(); 1450 1653 automatically_play_next = set->value( "automatically_play_next", automatically_play_next ).toBool(); 1654 ignore_player_errors = set->value( "ignore_player_errors", ignore_player_errors ).toBool(); 1451 1655 1452 1656 row_spacing = set->value( "row_spacing", row_spacing ).toInt();
Note:
See TracChangeset
for help on using the changeset viewer.