Index: mythmusic/cdrip.h =================================================================== --- mythmusic/cdrip.h (revision 12715) +++ mythmusic/cdrip.h (working copy) @@ -63,7 +63,7 @@ private: virtual void run(void); - int ripTrack(QString &cddevice, Encoder *encoder, int tracknum); + int ripTrack(QString &cddevice, Encoder *encoder, int tracknum, int tracklast); void sendEvent(int eventType, const QString &value); void sendEvent(int eventType, int value); @@ -111,10 +111,13 @@ void searchArtist(void); void searchAlbum(void); void searchGenre(void); + void titleChanged(QString newtitle); + void searchTitle(void); private: void wireupTheme(void); void keyPressEvent(QKeyEvent *e); + bool isNewTune(QString &artist, QString &album, QString &title); void deleteTrack(QString& artist, QString& album, QString& title); void updateTrackList(void); void trackListDown(bool page); @@ -138,12 +141,14 @@ UIPushButtonType *m_searchArtistButton; UIPushButtonType *m_searchAlbumButton; UIPushButtonType *m_searchGenreButton; + UIRemoteEditType *m_titleEdit; + UIPushButtonType *m_searchTitleButton; int m_currentTrack; int m_totalTracks; vector *m_tracks; - QString m_albumName, m_artistName, m_genreName, m_year; + QString m_albumName, m_artistName, m_genreName, m_year, m_titleName; QStringList m_searchList; bool m_somethingwasripped; bool m_mediaMonitorActive; Index: mythmusic/music-ui.xml =================================================================== --- mythmusic/music-ui.xml (revision 12715) +++ mythmusic/music-ui.xml (working copy) @@ -495,6 +495,12 @@ labels Track No.: + + + + @@ -864,9 +881,10 @@ 10 - - - + + + + 7 Index: mythmusic/decoder.h =================================================================== --- mythmusic/decoder.h (revision 12715) +++ mythmusic/decoder.h (working copy) @@ -81,6 +81,7 @@ virtual Metadata *getMetadata(void); virtual MetaIO *doCreateTagger (void); virtual void commitMetadata(Metadata *mdata); + virtual void recalcLength(Metadata *mdata); // static methods static QStringList all(); Index: mythmusic/metadata.cpp =================================================================== --- mythmusic/metadata.cpp (revision 12715) +++ mythmusic/metadata.cpp (working copy) @@ -513,6 +513,18 @@ } +QString Metadata::ReorderArtist() +{ + if (reorderartist.isEmpty()) { + QStringList artistreorder = QStringList::split(QRegExp("[>,]"), formattedartist); + formattedartist = artistreorder[1].stripWhiteSpace() + " " + + artistreorder[0].stripWhiteSpace(); + reorderartist = "Y"; + } + return formattedartist; +} + + QString Metadata::FormatTitle() { if (formattedtitle.isEmpty()) @@ -613,6 +625,12 @@ changed = true; } +void Metadata::setTrackLast(int ltracklast) +{ + tracklast = ltracklast; + changed = true; +} + QStringList Metadata::fillFieldList(QString field) { QStringList searchList; @@ -952,6 +970,8 @@ a_label += music_map[an_id]->FormatArtist(); a_label += " ~ "; + //a_label += music_map[an_id]->Album(); + //a_label += " ~ "; a_label += music_map[an_id]->FormatTitle(); Index: mythmusic/cddecoder.h =================================================================== --- mythmusic/cddecoder.h (revision 12715) +++ mythmusic/cddecoder.h (working copy) @@ -29,6 +29,7 @@ Metadata *getMetadata(void); Metadata *getLastMetadata(void); void commitMetadata(Metadata *mdata); + void recalcLength(Metadata *mdata); private: void run(); Index: mythmusic/cdrip.cpp =================================================================== --- mythmusic/cdrip.cpp (revision 12715) +++ mythmusic/cdrip.cpp (working copy) @@ -81,6 +81,7 @@ } // we only care about audio tracks + //just counting sectors, don't need tracklast if (cdda_track_audiop (device, tracknum)) { cdda_verbose_set(device, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); @@ -240,8 +241,13 @@ break; } - ripTrack(cddevice, encoder, trackno + 1); - + //trackno is the counter, 0-start + int trackfirst = trackno + 1; + int tracklast = track->TrackLast(); + ripTrack(cddevice, encoder, trackfirst, tracklast); + //counter to end of current track selection, inc at the top + trackno = tracklast - 1; + if (isCancelled()) return; @@ -274,7 +280,7 @@ sendEvent(ST_FINISHED, ""); } -int CDRipperThread::ripTrack(QString &cddevice, Encoder *encoder, int tracknum) +int CDRipperThread::ripTrack(QString &cddevice, Encoder *encoder, int tracknum, int tracklast) { cdrom_drive *device = cdda_identify(cddevice.ascii(), 0, NULL); @@ -289,7 +295,7 @@ cdda_verbose_set(device, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); long int start = cdda_track_firstsector(device, tracknum); - long int end = cdda_track_lastsector(device, tracknum); + long int end = cdda_track_lastsector(device, tracklast); cdrom_paranoia *paranoia = paranoia_init(device); if (gContext->GetSetting("ParanoiaLevel") == "full") @@ -443,6 +449,20 @@ connect(m_searchAlbumButton, SIGNAL(pushed()), this, SLOT(searchAlbum())); } + m_titleEdit = getUIRemoteEditType("title_edit"); + if (m_titleEdit) + { + m_titleEdit->createEdit(this); + connect(m_titleEdit, SIGNAL(textChanged(QString)), this, SLOT(titleChanged(QString))); + } + + m_searchTitleButton = getUIPushButtonType("searchtitle_button"); + if (m_searchTitleButton) + { + connect(m_searchTitleButton, SIGNAL(pushed()), this, SLOT(searchTitle())); + } + + m_genreEdit = getUIRemoteEditType("genre_edit"); if (m_genreEdit) { @@ -629,6 +649,8 @@ track = m_decoder->getMetadata(trackno + 1); if (track) { + //default, tracklast = track, produces same behavior as before + track->setTrackLast(trackno + 1); if (track->Compilation()) { isCompilation = true; @@ -979,6 +1001,21 @@ m_albumName = newalbum; } +void Ripper::titleChanged(QString newtitle) +{ + Metadata *data; + + for (int trackno = 0; trackno < m_totalTracks; ++trackno) + { + data = m_tracks->at(trackno); + + if (data) + data->setTitle(newtitle); + } + + m_titleName = newtitle; +} + void Ripper::genreChanged(QString newgenre) { Metadata *data; @@ -1164,6 +1201,26 @@ m_trackList->SetUpArrow(skip > 0); m_trackList->SetDownArrow(skip + trackListSize < m_totalTracks); + //calculate which tracks are active + //and which are skipped by a previous tracklast + //skipped show tracklast as 0 and length as - + int j; + int is_active[m_totalTracks]; + for (j = 0; j < m_totalTracks; j++) + { + is_active[j]=1; + Metadata *tmptrack = m_tracks->at(j); + int next = tmptrack->TrackLast(); + if (next > m_totalTracks) + { + next = m_totalTracks; + } + for (int k=j+1; k < next; k++) + { + is_active[k]=0; + } + j = next - 1; + } int i; for (i = 0; i < trackListSize; i++) { @@ -1171,17 +1228,24 @@ break; Metadata *track = m_tracks->at(i + skip); - - m_trackList->SetItemText(i, 1, QString::number(track->Track())); - m_trackList->SetItemText(i, 2, track->Title()); - m_trackList->SetItemText(i, 3, track->Artist()); - int length = track->Length() / 1000; + + int tracklast = track->TrackLast(); + int length = track->Length() / 1000; int min, sec; min = length / 60; sec = length % 60; QString s; - s.sprintf("%02d:%02d", min, sec); - m_trackList->SetItemText(i, 4, s); + s.sprintf("%02d:%02d", min, sec); + if (is_active[i + skip] == 0) + { + tracklast = 0; + s.sprintf("-"); + } + m_trackList->SetItemText(i, 1, QString::number(track->Track())); + m_trackList->SetItemText(i, 2, QString::number(tracklast)); + m_trackList->SetItemText(i, 3, track->Title()); + m_trackList->SetItemText(i, 4, track->Artist()); + m_trackList->SetItemText(i, 5, s); if (i + skip == m_currentTrack) { @@ -1250,15 +1314,31 @@ } } +void Ripper::searchTitle() +{ + QString s; + + m_searchList = Metadata::fillFieldList("title"); + + s = m_titleEdit->getText(); + if (showList(tr("Select Title"), s)) + { + m_titleEdit->setText(s); + titleChanged(s); + } +} + + void Ripper::searchGenre() { QString s; // load genre list m_searchList.clear(); - for (int x = 0; x < genre_table_size; x++) - m_searchList.push_back(QString(genre_table[x])); - m_searchList.sort(); + //for (int x = 0; x < genre_table_size; x++) + // m_searchList.push_back(QString(genre_table[x])); + //m_searchList.sort(); + m_searchList = Metadata::fillFieldList("genre"); s = m_genreEdit->getText(); if (showList(tr("Select a Genre"), s)) Index: mythmusic/playlist.cpp =================================================================== --- mythmusic/playlist.cpp (revision 12715) +++ mythmusic/playlist.cpp (working copy) @@ -974,6 +974,7 @@ if (tmpdata) { QString a_string = QString("%1 ~ %2").arg(tmpdata->FormatArtist()).arg(tmpdata->FormatTitle()); + //QString a_string = QString(QObject::tr("%1 ~ %2 ~ %3")).arg(tmpdata->FormatArtist()).arg(tmpdata->Album()).arg(tmpdata->FormatTitle()); GenericTree *added_node = tree_to_write_to->addNode(a_string, it->getValue(), true); ++a_counter; added_node->setAttribute(0, 1); @@ -1040,7 +1041,8 @@ { QString a_string = QString("CD: %1 ~ %2 - %3") .arg(tmpdata->Track()).arg(tmpdata->FormatTitle()).arg(tmpdata->FormatArtist()); - + //QString a_string = QString(QObject::tr("CD: %1 ~ %2 ~ %3 - %4")) + //.arg(tmpdata->FormatArtist()).arg(tmpdata->Album()).arg(tmpdata->Track()).arg(tmpdata->FormatTitle()); if(tmpdata->FormatArtist().length() < 1 || tmpdata->FormatTitle().length() < 1) { Index: mythmusic/decoder.cpp =================================================================== --- mythmusic/decoder.cpp (revision 12715) +++ mythmusic/decoder.cpp (working copy) @@ -161,6 +161,11 @@ } } +//only cddecoder knows +void Decoder::recalcLength(Metadata *mdata) +{ +} + // static methods int Decoder::ignore_id3 = 0; Index: mythmusic/metadata.h =================================================================== --- mythmusic/metadata.h (revision 12715) +++ mythmusic/metadata.h (working copy) @@ -28,7 +28,7 @@ title = ltitle; formattedartist = ""; formattedtitle = ""; - genre = lgenre; + genre = lgenre; year = lyear; tracknum = ltracknum; length = llength; @@ -40,6 +40,7 @@ changed = false; show = true; format = lformat; + reorderartist = ""; } Metadata(const Metadata &other) @@ -85,6 +86,7 @@ QString FormatArtist(); QString FormatTitle(); + QString ReorderArtist(); QString Genre() { return genre; } void setGenre(const QString &lgenre) { genre = lgenre; } @@ -125,6 +127,9 @@ bool isVisible() { return show; } void setVisible(bool visible) { show = visible; } + int TrackLast() { return tracklast; } + void setTrackLast(int tracklast); + // track is part of a compilation album bool Compilation() { return compilation; } void setCompilation(bool state) { compilation = state; formattedartist = formattedtitle = ""; } @@ -162,6 +167,8 @@ QString lastplay; int playcount; bool compilation; + QString reorderartist; + int tracklast; unsigned int id; QString filename; Index: mythmusic/editmetadata.cpp =================================================================== --- mythmusic/editmetadata.cpp (revision 12715) +++ mythmusic/editmetadata.cpp (working copy) @@ -102,6 +102,14 @@ { compilation_check->setState(m_metadata->Compilation()); } + + if (tracklast_edit) + { + QString s; + s = s.setNum(m_metadata->TrackLast()); + tracklast_edit->setText(s); + } + } void EditMetadataDialog::incRating(bool up_or_down) @@ -227,6 +235,13 @@ track_edit->createEdit(this); connect(track_edit, SIGNAL(loosingFocus()), this, SLOT(editLostFocus())); } + + tracklast_edit = getUIRemoteEditType("tracklast_edit"); + if (tracklast_edit) + { + tracklast_edit->createEdit(this); + connect(tracklast_edit, SIGNAL(loosingFocus()), this, SLOT(editLostFocus())); + } lastplay_text = getUITextType("lastplay_text"); playcount_text = getUITextType("playcount_text"); @@ -256,6 +271,12 @@ { connect(searchalbum_button, SIGNAL(pushed()), this, SLOT(searchAlbum())); } + + searchtitle_button = getUIPushButtonType("searchtitle_button"); + if (searchtitle_button) + { + connect(searchtitle_button, SIGNAL(pushed()), this, SLOT(searchAlbum())); + } searchgenre_button = getUIPushButtonType("searchgenre_button"); if (searchgenre_button) @@ -316,6 +337,10 @@ else if (whichEditor == track_edit) { m_metadata->setTrack(track_edit->getText().toInt()); + } + else if (whichEditor == tracklast_edit) + { + m_metadata->setTrackLast(tracklast_edit->getText().toInt()); } } @@ -489,6 +514,20 @@ cancelPopup(); *m_sourceMetadata = m_metadata; + //update length in case a tracklast has been added + Decoder *decoder = Decoder::create(m_metadata->Filename(), NULL, NULL, true); + if (decoder) + { + decoder->recalcLength(m_metadata); + delete decoder; + } + *m_sourceMetadata = m_metadata; + if (m_metadata->TrackLast() < m_metadata->Track()) + { + m_metadata->setTrackLast(m_metadata->Track()); + } + //set tracklast in the new metadata copy + m_sourceMetadata->setTrackLast(m_metadata->TrackLast()); done(1); } Index: mythmusic/editmetadata.h =================================================================== --- mythmusic/editmetadata.h (revision 12715) +++ mythmusic/editmetadata.h (working copy) @@ -64,7 +64,8 @@ UIRemoteEditType *genre_edit; UIRemoteEditType *year_edit; UIRemoteEditType *track_edit; - + UIRemoteEditType *tracklast_edit; + UITextType *lastplay_text; UITextType *playcount_text; UITextType *filename_text; @@ -74,8 +75,9 @@ UIPushButtonType *searchartist_button; UIPushButtonType *searchcompilation_artist_button; UIPushButtonType *searchalbum_button; - UIPushButtonType *searchgenre_button; + UIPushButtonType *searchgenre_button; UIPushButtonType *rating_button; + UIPushButtonType *searchtitle_button; UICheckBoxType *compilation_check; Index: mythmusic/playbackbox.h =================================================================== --- mythmusic/playbackbox.h (revision 12715) +++ mythmusic/playbackbox.h (working copy) @@ -87,6 +87,7 @@ void byAlbum(); void byGenre(); void byYear(); + void byTitle(); void fromCD(); void showSmartPlaylistDialog(); void showSearchDialog(); Index: mythmusic/cddecoder.cpp =================================================================== --- mythmusic/cddecoder.cpp (revision 12715) +++ mythmusic/cddecoder.cpp (working copy) @@ -437,6 +437,62 @@ return retdata; } +void CdDecoder::recalcLength(Metadata *mdata) +{ + int cd = cd_init_device((char *)devicename.ascii()); + + struct disc_info discinfo; + if (cd_stat(cd, &discinfo) != 0) + { + error("Couldn't stat CD, Error."); + cd_finish(cd); + } + + if (!discinfo.disc_present) + { + error("No disc present"); + cd_finish(cd); + } + + int tracknum = mdata->Track(); + int tracklast = mdata->TrackLast(); + + if (tracknum > discinfo.disc_total_tracks) + { + error("No such track on CD"); + cd_finish(cd); + return; + } + + if (tracklast > discinfo.disc_total_tracks) + { + error("No such track on CD"); + cd_finish(cd); + return; + } + + if (tracklast < tracknum) + { + error("Negative-length track"); + cd_finish(cd); + return; + } + + int length = 0; + for (int i = tracknum - 1; i < tracklast; i++) + { + int ltemp = discinfo.disc_track[i].track_length.minutes * 60 + + discinfo.disc_track[i].track_length.seconds; + ltemp = ltemp < 0 ? 0 : ltemp; + length += ltemp; + } + length *= 1000; + VERBOSE(VB_IMPORTANT, QString("Recalculating length to %1").arg(length)); + mdata->setLength(length); + cd_finish(cd); + return; +} + void CdDecoder::commitMetadata(Metadata *mdata) { int cd = cd_init_device((char *)devicename.ascii());