![]() |
Mixxx
|
00001 // dlgtrackinfo.cpp 00002 // Created 11/10/2009 by RJ Ryan (rryan@mit.edu) 00003 00004 #include <QtDebug> 00005 00006 #include "dlgtrackinfo.h" 00007 #include "library/dao/cue.h" 00008 #include "trackinfoobject.h" 00009 00010 DlgTrackInfo::DlgTrackInfo(QWidget* parent) : 00011 QDialog(parent), 00012 m_pLoadedTrack() { 00013 00014 setupUi(this); 00015 00016 cueTable->hideColumn(0); 00017 00018 connect(btnNext, SIGNAL(clicked()), 00019 this, SLOT(slotNext())); 00020 connect(btnPrev, SIGNAL(clicked()), 00021 this, SLOT(slotPrev())); 00022 connect(btnApply, SIGNAL(clicked()), 00023 this, SLOT(apply())); 00024 connect(btnCancel, SIGNAL(clicked()), 00025 this, SLOT(cancel())); 00026 00027 connect(bpmDouble, SIGNAL(clicked()), 00028 this, SLOT(slotBpmDouble())); 00029 connect(bpmHalve, SIGNAL(clicked()), 00030 this, SLOT(slotBpmHalve())); 00031 connect(bpmTap, SIGNAL(pressed()), 00032 this, SLOT(slotBpmTap())); 00033 00034 connect(btnCueActivate, SIGNAL(clicked()), 00035 this, SLOT(cueActivate())); 00036 connect(btnCueDelete, SIGNAL(clicked()), 00037 this, SLOT(cueDelete())); 00038 00039 connect(btnReloadFromFile, SIGNAL(clicked()), 00040 this, SLOT(reloadTrackMetadata())); 00041 00042 m_bpmTapTimer.start(); 00043 for (int i = 0; i < filterLength; ++i) { 00044 m_bpmTapFilter[i] = 0.0f; 00045 } 00046 } 00047 00048 DlgTrackInfo::~DlgTrackInfo() { 00049 unloadTrack(false); 00050 qDebug() << "~DlgTrackInfo()"; 00051 } 00052 00053 void DlgTrackInfo::apply() { 00054 unloadTrack(true); 00055 accept(); 00056 } 00057 00058 void DlgTrackInfo::cancel() { 00059 unloadTrack(false); 00060 reject(); 00061 } 00062 00063 void DlgTrackInfo::trackUpdated() { 00064 00065 } 00066 00067 void DlgTrackInfo::slotNext() { 00068 emit(next()); 00069 } 00070 00071 void DlgTrackInfo::slotPrev() { 00072 emit(previous()); 00073 } 00074 00075 void DlgTrackInfo::cueActivate() { 00076 00077 } 00078 00079 void DlgTrackInfo::cueDelete() { 00080 QList<QTableWidgetItem*> selected = cueTable->selectedItems(); 00081 QListIterator<QTableWidgetItem*> item_it(selected); 00082 00083 QSet<int> rowsToDelete; 00084 while(item_it.hasNext()) { 00085 QTableWidgetItem* item = item_it.next(); 00086 rowsToDelete.insert(item->row()); 00087 } 00088 00089 QList<int> rowsList = QList<int>::fromSet(rowsToDelete); 00090 qSort(rowsList); 00091 00092 QListIterator<int> it(rowsList); 00093 it.toBack(); 00094 while (it.hasPrevious()) { 00095 cueTable->removeRow(it.previous()); 00096 } 00097 } 00098 00099 void DlgTrackInfo::populateFields(TrackPointer pTrack) { 00100 // Editable fields 00101 lblSong->setText(pTrack->getTitle()); 00102 txtTrackName->setText(pTrack->getTitle()); 00103 txtArtist->setText(pTrack->getArtist()); 00104 txtAlbum->setText(pTrack->getAlbum()); 00105 txtGenre->setText(pTrack->getGenre()); 00106 txtYear->setText(pTrack->getYear()); 00107 txtTrackNumber->setText(pTrack->getTrackNumber()); 00108 txtComment->setText(pTrack->getComment()); 00109 spinBpm->setValue(pTrack->getBpm()); 00110 00111 // Non-editable fields 00112 txtDuration->setText(pTrack->getDurationStr()); 00113 txtFilepath->setText(pTrack->getFilename()); 00114 txtFilepath->setCursorPosition(0); 00115 txtType->setText(pTrack->getType()); 00116 } 00117 00118 void DlgTrackInfo::loadTrack(TrackPointer pTrack) { 00119 m_pLoadedTrack = pTrack; 00120 clear(); 00121 00122 if (m_pLoadedTrack == NULL) 00123 return; 00124 00125 populateFields(m_pLoadedTrack); 00126 populateCues(m_pLoadedTrack); 00127 } 00128 00129 void DlgTrackInfo::populateCues(TrackPointer pTrack) { 00130 int sampleRate = pTrack->getSampleRate(); 00131 00132 QList<Cue*> listPoints; 00133 const QList<Cue*>& cuePoints = pTrack->getCuePoints(); 00134 QListIterator<Cue*> it(cuePoints); 00135 while (it.hasNext()) { 00136 Cue* pCue = it.next(); 00137 if (pCue->getType() == Cue::CUE || pCue->getType() == Cue::LOAD) { 00138 listPoints.push_back(pCue); 00139 } 00140 } 00141 it = QListIterator<Cue*>(listPoints); 00142 cueTable->setSortingEnabled(false); 00143 int row = 0; 00144 00145 while (it.hasNext()) { 00146 Cue* pCue = it.next(); 00147 00148 QString rowStr = QString("%1").arg(row); 00149 00150 // All hotcues are stored in Cue's as 0-indexed, but the GUI presents 00151 // them to the user as 1-indexex. Add 1 here. rryan 9/2010 00152 int iHotcue = pCue->getHotCue() + 1; 00153 QString hotcue = ""; 00154 if (iHotcue != -1) { 00155 hotcue = QString("%1").arg(iHotcue); 00156 } 00157 00158 int position = pCue->getPosition(); 00159 double totalSeconds; 00160 if (position == -1) 00161 continue; 00162 else { 00163 totalSeconds = float(position) / float(sampleRate) / 2.0; 00164 } 00165 00166 int fraction = 100*(totalSeconds - floor(totalSeconds)); 00167 int seconds = int(totalSeconds) % 60; 00168 int mins = int(totalSeconds) / 60; 00169 //int hours = mins / 60; //Not going to worry about this for now. :) 00170 00171 //Construct a nicely formatted duration string now. 00172 QString duration = QString("%1:%2.%3").arg(mins).arg(seconds, 2, 10, QChar('0')).arg(fraction, 2,10, QChar('0')); 00173 00174 QTableWidgetItem* durationItem = new QTableWidgetItem(duration); 00175 // Make the duration read only 00176 durationItem->setFlags(Qt::NoItemFlags); 00177 00178 m_cueMap[row] = pCue; 00179 cueTable->insertRow(row); 00180 cueTable->setItem(row, 0, new QTableWidgetItem(rowStr)); 00181 cueTable->setItem(row, 1, durationItem); 00182 cueTable->setItem(row, 2, new QTableWidgetItem(hotcue)); 00183 cueTable->setItem(row, 3, new QTableWidgetItem(pCue->getLabel())); 00184 row += 1; 00185 } 00186 cueTable->setSortingEnabled(true); 00187 } 00188 00189 void DlgTrackInfo::unloadTrack(bool save) { 00190 if (!m_pLoadedTrack) 00191 return; 00192 00193 if (save) { 00194 m_pLoadedTrack->setTitle(txtTrackName->text()); 00195 m_pLoadedTrack->setArtist(txtArtist->text()); 00196 m_pLoadedTrack->setAlbum(txtAlbum->text()); 00197 m_pLoadedTrack->setGenre(txtGenre->text()); 00198 m_pLoadedTrack->setYear(txtYear->text()); 00199 m_pLoadedTrack->setTrackNumber(txtTrackNumber->text()); 00200 m_pLoadedTrack->setBpm(spinBpm->value()); 00201 m_pLoadedTrack->setComment(txtComment->toPlainText()); 00202 00203 QHash<int, Cue*> cueMap; 00204 for (int row = 0; row < cueTable->rowCount(); ++row) { 00205 00206 QTableWidgetItem* rowItem = cueTable->item(row, 0); 00207 QTableWidgetItem* hotcueItem = cueTable->item(row, 2); 00208 QTableWidgetItem* labelItem = cueTable->item(row, 3); 00209 00210 if (!rowItem || !hotcueItem || !labelItem) 00211 continue; 00212 00213 int oldRow = rowItem->data(Qt::DisplayRole).toInt(); 00214 Cue* pCue = m_cueMap.take(oldRow); 00215 00216 QVariant vHotcue = hotcueItem->data(Qt::DisplayRole); 00217 if (vHotcue.canConvert<int>()) { 00218 int iTableHotcue = vHotcue.toInt(); 00219 // The GUI shows hotcues as 1-indexed, but they are actually 00220 // 0-indexed, so subtract 1 00221 pCue->setHotCue(iTableHotcue-1); 00222 } else { 00223 pCue->setHotCue(-1); 00224 } 00225 00226 QString label = labelItem->data(Qt::DisplayRole).toString(); 00227 pCue->setLabel(label); 00228 } 00229 00230 QMutableHashIterator<int,Cue*> it(m_cueMap); 00231 // Everything remaining in m_cueMap must have been deleted. 00232 while (it.hasNext()) { 00233 it.next(); 00234 Cue* pCue = it.value(); 00235 it.remove(); 00236 qDebug() << "Deleting cue" << pCue->getId() << pCue->getHotCue(); 00237 m_pLoadedTrack->removeCue(pCue); 00238 } 00239 } 00240 00241 m_pLoadedTrack.clear(); 00242 clear(); 00243 } 00244 00245 void DlgTrackInfo::clear() { 00246 txtTrackName->setText(""); 00247 lblSong->setText("Track:"); 00248 00249 txtTrackName->setText(""); 00250 txtArtist->setText(""); 00251 txtAlbum->setText(""); 00252 txtGenre->setText(""); 00253 txtYear->setText(""); 00254 txtTrackNumber->setText(""); 00255 txtComment->setText(""); 00256 spinBpm->setValue(0.0); 00257 00258 txtDuration->setText(""); 00259 txtFilepath->setText(""); 00260 txtType->setText(""); 00261 00262 m_cueMap.clear(); 00263 cueTable->clearContents(); 00264 cueTable->setRowCount(0); 00265 } 00266 00267 void DlgTrackInfo::slotBpmDouble() { 00268 spinBpm->setValue(spinBpm->value() * 2.0); 00269 } 00270 00271 void DlgTrackInfo::slotBpmHalve() { 00272 spinBpm->setValue(spinBpm->value() / 2.0); 00273 } 00274 00275 void DlgTrackInfo::slotBpmTap() { 00276 int elapsed = m_bpmTapTimer.elapsed(); 00277 m_bpmTapTimer.restart(); 00278 00279 if (elapsed <= maxInterval) { 00280 // Move back in filter one sample 00281 for (int i = 1; i < filterLength; ++i) { 00282 m_bpmTapFilter[i-1] = m_bpmTapFilter[i]; 00283 } 00284 00285 m_bpmTapFilter[filterLength-1] = 60000.0f/elapsed; 00286 if (m_bpmTapFilter[filterLength-1] > maxBPM) 00287 m_bpmTapFilter[filterLength-1] = maxBPM; 00288 00289 double temp = 0.; 00290 for (int i = 0; i < filterLength; ++i) { 00291 temp += m_bpmTapFilter[i]; 00292 } 00293 temp /= filterLength; 00294 spinBpm->setValue(temp); 00295 } 00296 } 00297 00298 void DlgTrackInfo::reloadTrackMetadata() { 00299 if (m_pLoadedTrack) { 00300 TrackPointer pTrack(new TrackInfoObject(m_pLoadedTrack->getLocation())); 00301 populateFields(pTrack); 00302 } 00303 }