Version: 1.4.4 (using KDE KDE 3.5.5) Installed from: Ubuntu Packages OS: Linux I discovered that I could create live updating smart playlists on my iPod using gtkpod. However, my "Recently Unplayed" smart playlist didn't work as expected, and after some investigation I found that Amarok doesn't synchronise the Last Played time to the iPod. So I fixed it :-) My patch synchronises Play Counts and Last Played timestamps to the iPod. This is done in the same place where Ratings are synchronised, and so is enabled/disabled with the "Synchronize with Amarok statistics" option. It also sets the "Date Added" and "Date Modified" timestamps when transferring files to the iPod. There are a few issues however, which I will describe with the patch.
Created attachment 18374 [details] Synchronise Play Count and Last Played to iPod, and set Date Added and Date Modified on transfer There are two issues with my patch. The first is that I was unsure about this code, found in IpodMediaDevice::setRating(). if( dynamic_cast<IpodMediaDevice *>(device()) ) static_cast<IpodMediaDevice *>(device())->m_dbChanged = true; It seems to mark the database as changed so that it gets written when the iPod is disconnected. This happens regardless though, because IpodMediaDevice::writeITunesDB() always sets dbChanged to true. In case it does something I don't understand, I've added it to my setPlayCount() and setLastPlayed() methods. The second issue is that I can't find a nice way to get "modifydate" from the database. I've used QueryBuilder to get the "createdate" for tracks, but it doesn't have a field for "modifydate". So I just set both "time_added" and "time_modified" to the "createdate".
SVN commit 608923 by aumuell: synchronize play count, last played time and date of modification to ipods - thanks to Michael <michael003@gmail.com> for the patch BUG: 136759 M +2 -0 ChangeLog M +3 -1 src/mediabrowser.cpp M +2 -0 src/mediabrowser.h M +29 -0 src/mediadevice/ipod/ipodmediadevice.cpp --- trunk/extragear/multimedia/amarok/ChangeLog #608922:608923 @@ -5,6 +5,8 @@ VERSION 1.4.5 FEATURES: + * Synchronize play count, last played time and date of modification to + iPods. Patch by Michael <michael003@gmail.com>. (BR 136759) * Propose list of composers in collection when editing the composer tag from the playlist. (BR 137775) * Greatly improved sound quality for the xine equalizer. Patch by Tobias --- trunk/extragear/multimedia/amarok/src/mediabrowser.cpp #608922:608923 @@ -2823,9 +2823,11 @@ if( url != QString::null ) { - // copy Amarok rating to device + // copy Amarok rating, play count and last played time to device int rating = CollectionDB::instance()->getSongRating( url )*10; it->setRating( rating ); + it->setPlayCount( CollectionDB::instance()->getPlayCount( url ) ); + it->setLastPlayed( CollectionDB::instance()->getLastPlay( url ).toTime_t() ); } } break; --- trunk/extragear/multimedia/amarok/src/mediabrowser.h #608922:608923 @@ -76,9 +76,11 @@ virtual QDateTime playTime() const { return QDateTime(); } virtual int played() const { return 0; } virtual int recentlyPlayed() const { return 0; } // no of times played on device since last sync + virtual void setPlayCount( int ) {} virtual int rating() const { return 0; } // rating on device, normalized to 100 virtual void setRating( int /*rating*/ ) {} virtual bool ratingChanged() const { return false; } + virtual void setLastPlayed( uint ) {} virtual long size() const; virtual MediaDevice *device() const { return m_device; } virtual bool listened() const { return m_listened; } --- trunk/extragear/multimedia/amarok/src/mediadevice/ipod/ipodmediadevice.cpp #608922:608923 @@ -164,6 +164,22 @@ static_cast<IpodMediaDevice *>(device())->m_dbChanged = true; } + void setPlayCount( int playcount ) + { + if ( m_track ) + m_track->playcount = playcount; + if( dynamic_cast<IpodMediaDevice *>(device()) ) + static_cast<IpodMediaDevice *>(device())->m_dbChanged = true; + } + + void setLastPlayed( uint lastplay ) + { + if ( m_track ) + m_track->time_played = itdb_time_host_to_mac( lastplay ); + if( dynamic_cast<IpodMediaDevice *>(device()) ) + static_cast<IpodMediaDevice *>(device())->m_dbChanged = true; + } + bool ratingChanged() const { return m_track ? m_track->rating != m_track->app_rating : false; } void setListened( bool l ) @@ -387,6 +403,19 @@ track->samplerate = propertiesBundle.sampleRate(); track->tracklen = propertiesBundle.length()*1000; + //Get the createdate from database + QueryBuilder qb; + qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valCreateDate ); + qb.addMatch( QueryBuilder::tabSong, QueryBuilder::valURL, metaBundle.url().path() ); + QStringList values = qb.run(); + + //Add to track info if present + if ( values.count() ) { + uint createdate = values.first().toUInt(); + track->time_added = itdb_time_host_to_mac( createdate ); + track->time_modified = itdb_time_host_to_mac( createdate ); + } + if(podcastInfo) { #ifdef HAVE_ITDB_SKIP_SHUFFLE_FLAG
Does this mean that the changed statistics are always copied to the iPod even if the play count on the iPod is higher?
This will happen: but if you always sync your ipod to the same computer, then all plays have been synced to your computer and the play count on your computer is at least as high as on your ipod.
There are actually two play count values on the iPod. The first is the total play count, which is stored in the "iTunesDB" file. This value is not modified by the iPod (the iPod does not change the "iTunesDB" file at all). The second value is the play count since the last sync. This value is stored in the "Play Counts" file and is reset to 0 when the iPod is synchronised. When the iPod is synchronised Amarok adds the play count from the "Play Counts" file (i.e. the number of times the track was played on the iPod since the last sync) to it's own play count. My patch makes Amarok write the play count (the updated total play count) to the "iTunesDB" file.