Summary: | Podcasts are duplicated on update | ||
---|---|---|---|
Product: | [Applications] amarok | Reporter: | Zdeněk Zikán <zdenek.zikan> |
Component: | Podcast | Assignee: | Amarok Developers <amarok-bugs-dist> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | bart.cerneels, bjorn.ballard, pcbadger, per.lindstrom68 |
Priority: | NOR | ||
Version: | 2.3.0 | ||
Target Milestone: | --- | ||
Platform: | unspecified | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | 2.3.1 | |
Sentry Crash Report: | |||
Attachments: |
First run
Second run after another update of the podcast |
Description
Zdeněk Zikán
2010-03-18 16:24:59 UTC
-> over to Podcasts and Bart Does this happen with all channels or is there a specific one this happens with? Please paste the url of that channel here. I tried it with these two podcasts: http://www2.rozhlas.cz/podcast/radiozurnal.rss http://downloads.bbc.co.uk/podcasts/worldservice/docarchive/rss.xml and it happens with both of them (no matter whether I update them one-by-one or "Update All") *** Bug 231809 has been marked as a duplicate of this bug. *** I can't reproduce this. There might be something wrong with your database. Is this a normal setup or do you use a MySQL server? Could you please run the next command in the script console and attach the result in a text file. Amarok.Collection.query( "SELECT id, title, url, guid FROM podcastepisodes WHERE channel = (SELECT id FROM podcastchannels WHERE url='http://www2.rozhlas.cz/podcast/radiozurnal.rss');" ); (In reply to comment #5) > I can't reproduce this. There might be something wrong with your database. Is > this a normal setup or do you use a MySQL server? > > Could you please run the next command in the script console and attach the > result in a text file. > > Amarok.Collection.query( "SELECT id, title, url, guid FROM podcastepisodes > WHERE channel = (SELECT id FROM podcastchannels WHERE > url='http://www2.rozhlas.cz/podcast/radiozurnal.rss');" ); I have the same problem with podcasts from NRK (http://nrk.no/podkast/), for example http://podkast.nrk.no/program/naturtelefonen.rss. I ran the above command substituting the url, but I don't konw how to copy the text from the script console. (In reply to comment #6) > I have the same problem with podcasts from NRK (http://nrk.no/podkast/), for > example http://podkast.nrk.no/program/naturtelefonen.rss. I ran the above > command substituting the url, but I don't konw how to copy the text from the > script console. Select the line and Ctrl+C. Make sure to paste it in a text file and attach it here. The content will be to long to parse in a comment. Created attachment 42228 [details]
First run
Created attachment 42229 [details]
Second run after another update of the podcast
It stopped doing after update to a newer version of Kubuntu package (now I have 2:2.3.0-0ubuntu1~karmic1~ppa2), so I'm not sure whether it was bug that was in Ubuntu package only or whether it was Amarok bug fixed by Ubuntu devs. *** Bug 232032 has been marked as a duplicate of this bug. *** commit d799a6ca67a3eb7ab0409948d40777ecdb70d745 Author: Bart Cerneels <bart.cerneels@kde.org> Date: Thu Mar 25 20:13:04 2010 +0100 Work around KUrl string parsing for guids. trackForUrl can not be used to query by guid because urls are not allowed to have non-latin characters, spaces, percent encoded entries, capitals, etc. So we'll use a function that doesn't take a KUrl. BUG:231230 diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp index 3a8ce5b..7700a16 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp @@ -55,6 +55,13 @@ UmsPodcastProvider::trackForUrl( const KUrl &url ) return TrackPtr(); } +PodcastEpisodePtr +UmsPodcastProvider::episodeForGuid( const QString &guid ) +{ + Q_UNUSED( guid ) + return PodcastEpisodePtr(); +} + void UmsPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.h b/src/collection/umscollection/podcasts/UmsPodcastProvider.h index 059ed45..f052769 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.h +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.h @@ -36,6 +36,8 @@ class UmsPodcastProvider : public PodcastProvider virtual bool possiblyContainsTrack( const KUrl &url ) const; virtual Meta::TrackPtr trackForUrl( const KUrl &url ); + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + virtual void addPodcast( const KUrl &url ); virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); diff --git a/src/podcasts/PodcastProvider.h b/src/podcasts/PodcastProvider.h index 6bda936..d670ec1 100644 --- a/src/podcasts/PodcastProvider.h +++ b/src/podcasts/PodcastProvider.h @@ -41,6 +41,14 @@ class AMAROK_EXPORT PodcastProvider : public Amarok::TrackProvider, public Playl virtual bool possiblyContainsTrack( const KUrl &url ) const = 0; virtual Meta::TrackPtr trackForUrl( const KUrl &url ) = 0; + /** Special function to get an episode for a given guid. + * + * note: this functions is required because KUrl does not preserve every possible guids. + * This means we can not use trackForUrl(). + * Problematic guids contain non-latin characters, percent encoded parts, capitals, etc. + */ + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ) = 0; + virtual void addPodcast( const KUrl &url ) = 0; virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ) = 0; diff --git a/src/podcasts/PodcastReader.cpp b/src/podcasts/PodcastReader.cpp index f609222..1722bd8 100644 --- a/src/podcasts/PodcastReader.cpp +++ b/src/podcasts/PodcastReader.cpp @@ -1149,15 +1149,18 @@ PodcastReader::endItem() m_item->setDescription( description ); } + Meta::PodcastEpisodePtr episode; QString guid = m_item->guid(); - bool useGuid = !guid.isEmpty() && - !guid.contains( "[A-Z]" ) && //KUrl only uses lowercase - !guid.startsWith( '/' ); //appends file:// - - const KUrl trackId( useGuid ? m_item->guid() : m_item->uidUrl() ); - Meta::PodcastEpisodePtr episode = Meta::PodcastEpisodePtr::dynamicCast( - m_podcastProvider->trackForUrl( trackId ) + if( guid.isEmpty() ) + { + episode = Meta::PodcastEpisodePtr::dynamicCast( + m_podcastProvider->trackForUrl( m_item->uidUrl() ) ); + } + else + { + episode = m_podcastProvider->episodeForGuid( guid ); + } //make sure that the episode is not a bogus match. The channel has to be correct. // See http://bugs.kde.org/show_bug.cgi?id=227515 diff --git a/src/podcasts/sql/SqlPodcastProvider.cpp b/src/podcasts/sql/SqlPodcastProvider.cpp index fa11604..a805867 100644 --- a/src/podcasts/sql/SqlPodcastProvider.cpp +++ b/src/podcasts/sql/SqlPodcastProvider.cpp @@ -170,47 +170,25 @@ SqlPodcastProvider::loadPodcasts() emit( updated() ); } -QString -SqlPodcastProvider::cleanUrlOrGuid( const KUrl &url ) +SqlPodcastEpisodePtr +SqlPodcastProvider::sqlEpisodeForString( const QString &string ) { - QString decodedUrl = QUrl::fromPercentEncoding( url.url().toUtf8() ); - return decodedUrl; -} + if( string.isEmpty() ) + return SqlPodcastEpisodePtr(); -bool -SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const -{ SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); if( !sqlStorage ) - return false; - - QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " - "OR localurl='%1';"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); - - QStringList dbResult = sqlStorage->query( command ); - return !dbResult.isEmpty(); -} - -Meta::TrackPtr -SqlPodcastProvider::trackForUrl( const KUrl &url ) -{ - if( url.isEmpty() ) - return TrackPtr(); - - SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); - if( !sqlStorage ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); QString command = "SELECT id, url, channel, localurl, guid, " "title, subtitle, sequencenumber, description, mimetype, pubdate, " "duration, filesize, isnew FROM podcastepisodes " "WHERE guid='%1' OR url='%1' OR localurl='%1' ORDER BY id DESC;"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); + command = command.arg( sqlStorage->escape( string ) ); QStringList dbResult = sqlStorage->query( command ); if( dbResult.isEmpty() ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); int episodeId = dbResult[0].toInt(); int channelId = dbResult[2].toInt(); @@ -229,23 +207,42 @@ SqlPodcastProvider::trackForUrl( const KUrl &url ) { error() << QString( "There is a track in the database with url/guid=%1 (%2) " "but there is no channel with dbId=%3 in our list!" ) - .arg( url.url() ).arg( episodeId ).arg( channelId ); - return TrackPtr(); + .arg( string ).arg( episodeId ).arg( channelId ); + return SqlPodcastEpisodePtr(); } Meta::SqlPodcastEpisodePtr episode; foreach( episode, channel->sqlEpisodes() ) - { if( episode->dbId() == episodeId ) - { - debug() << "found it!"; - return Meta::TrackPtr::dynamicCast( episode ); - } - } + return episode; //The episode was found in the database but it's channel didn't have it in it's list. //That probably is because it's beyond the purgecount limit. - episode = new Meta::SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ); + return SqlPodcastEpisodePtr( new SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ) ); +} + +bool +SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const +{ + SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); + if( !sqlStorage ) + return false; + + QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " + "OR localurl='%1';"; + command = command.arg( sqlStorage->escape( url.url() ) ); + + QStringList dbResult = sqlStorage->query( command ); + return !dbResult.isEmpty(); +} + +Meta::TrackPtr +SqlPodcastProvider::trackForUrl( const KUrl &url ) +{ + if( url.isEmpty() ) + return TrackPtr(); + + SqlPodcastEpisodePtr episode = sqlEpisodeForString( url.url() ); return Meta::TrackPtr::dynamicCast( episode ); } @@ -263,6 +260,12 @@ SqlPodcastProvider::playlists() return playlistList; } +Meta::PodcastEpisodePtr +SqlPodcastProvider::episodeForGuid( const QString &guid ) +{ + return PodcastEpisodePtr::dynamicCast( sqlEpisodeForString( guid ) ); +} + void SqlPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/podcasts/sql/SqlPodcastProvider.h b/src/podcasts/sql/SqlPodcastProvider.h index d45c968..0bfb20b 100644 --- a/src/podcasts/sql/SqlPodcastProvider.h +++ b/src/podcasts/sql/SqlPodcastProvider.h @@ -50,6 +50,8 @@ class SqlPodcastProvider : public PodcastProvider Meta::PlaylistList playlists(); //PodcastProvider methods + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + void addPodcast( const KUrl &url ); Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); @@ -114,9 +116,8 @@ class SqlPodcastProvider : public PodcastProvider void createTables() const; void loadPodcasts(); - /** return the url as a string. Removes percent encoding if it actually has a non-url guid. - */ - static QString cleanUrlOrGuid( const KUrl &url ); + /** @arg string: a url, localUrl or guid in string form */ + Meta::SqlPodcastEpisodePtr sqlEpisodeForString( const QString &string ); void updateDatabase( int fromVersion, int toVersion ); void fetchImage( Meta::SqlPodcastChannelPtr channel ); This has just been fixed by Bart: commit d799a6ca67a3eb7ab0409948d40777ecdb70d745 Author: Bart Cerneels <bart.cerneels@kde.org> Date: Thu Mar 25 20:13:04 2010 +0100 Work around KUrl string parsing for guids. trackForUrl can not be used to query by guid because urls are not allowed to have non-latin characters, spaces, percent encoded entries, capitals, etc. So we'll use a function that doesn't take a KUrl. BUG:231230 diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp index 3a8ce5b..7700a16 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp @@ -55,6 +55,13 @@ UmsPodcastProvider::trackForUrl( const KUrl &url ) return TrackPtr(); } +PodcastEpisodePtr +UmsPodcastProvider::episodeForGuid( const QString &guid ) +{ + Q_UNUSED( guid ) + return PodcastEpisodePtr(); +} + void UmsPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.h b/src/collection/umscollection/podcasts/UmsPodcastProvider.h index 059ed45..f052769 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.h +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.h @@ -36,6 +36,8 @@ class UmsPodcastProvider : public PodcastProvider virtual bool possiblyContainsTrack( const KUrl &url ) const; virtual Meta::TrackPtr trackForUrl( const KUrl &url ); + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + virtual void addPodcast( const KUrl &url ); virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); diff --git a/src/podcasts/PodcastProvider.h b/src/podcasts/PodcastProvider.h index 6bda936..d670ec1 100644 --- a/src/podcasts/PodcastProvider.h +++ b/src/podcasts/PodcastProvider.h @@ -41,6 +41,14 @@ class AMAROK_EXPORT PodcastProvider : public Amarok::TrackProvider, public Playl virtual bool possiblyContainsTrack( const KUrl &url ) const = 0; virtual Meta::TrackPtr trackForUrl( const KUrl &url ) = 0; + /** Special function to get an episode for a given guid. + * + * note: this functions is required because KUrl does not preserve every possible guids. + * This means we can not use trackForUrl(). + * Problematic guids contain non-latin characters, percent encoded parts, capitals, etc. + */ + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ) = 0; + virtual void addPodcast( const KUrl &url ) = 0; virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ) = 0; diff --git a/src/podcasts/PodcastReader.cpp b/src/podcasts/PodcastReader.cpp index f609222..1722bd8 100644 --- a/src/podcasts/PodcastReader.cpp +++ b/src/podcasts/PodcastReader.cpp @@ -1149,15 +1149,18 @@ PodcastReader::endItem() m_item->setDescription( description ); } + Meta::PodcastEpisodePtr episode; QString guid = m_item->guid(); - bool useGuid = !guid.isEmpty() && - !guid.contains( "[A-Z]" ) && //KUrl only uses lowercase - !guid.startsWith( '/' ); //appends file:// - - const KUrl trackId( useGuid ? m_item->guid() : m_item->uidUrl() ); - Meta::PodcastEpisodePtr episode = Meta::PodcastEpisodePtr::dynamicCast( - m_podcastProvider->trackForUrl( trackId ) + if( guid.isEmpty() ) + { + episode = Meta::PodcastEpisodePtr::dynamicCast( + m_podcastProvider->trackForUrl( m_item->uidUrl() ) ); + } + else + { + episode = m_podcastProvider->episodeForGuid( guid ); + } //make sure that the episode is not a bogus match. The channel has to be correct. // See http://bugs.kde.org/show_bug.cgi?id=227515 diff --git a/src/podcasts/sql/SqlPodcastProvider.cpp b/src/podcasts/sql/SqlPodcastProvider.cpp index fa11604..a805867 100644 --- a/src/podcasts/sql/SqlPodcastProvider.cpp +++ b/src/podcasts/sql/SqlPodcastProvider.cpp @@ -170,47 +170,25 @@ SqlPodcastProvider::loadPodcasts() emit( updated() ); } -QString -SqlPodcastProvider::cleanUrlOrGuid( const KUrl &url ) +SqlPodcastEpisodePtr +SqlPodcastProvider::sqlEpisodeForString( const QString &string ) { - QString decodedUrl = QUrl::fromPercentEncoding( url.url().toUtf8() ); - return decodedUrl; -} + if( string.isEmpty() ) + return SqlPodcastEpisodePtr(); -bool -SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const -{ SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); if( !sqlStorage ) - return false; - - QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " - "OR localurl='%1';"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); - - QStringList dbResult = sqlStorage->query( command ); - return !dbResult.isEmpty(); -} - -Meta::TrackPtr -SqlPodcastProvider::trackForUrl( const KUrl &url ) -{ - if( url.isEmpty() ) - return TrackPtr(); - - SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); - if( !sqlStorage ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); QString command = "SELECT id, url, channel, localurl, guid, " "title, subtitle, sequencenumber, description, mimetype, pubdate, " "duration, filesize, isnew FROM podcastepisodes " "WHERE guid='%1' OR url='%1' OR localurl='%1' ORDER BY id DESC;"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); + command = command.arg( sqlStorage->escape( string ) ); QStringList dbResult = sqlStorage->query( command ); if( dbResult.isEmpty() ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); int episodeId = dbResult[0].toInt(); int channelId = dbResult[2].toInt(); @@ -229,23 +207,42 @@ SqlPodcastProvider::trackForUrl( const KUrl &url ) { error() << QString( "There is a track in the database with url/guid=%1 (%2) " "but there is no channel with dbId=%3 in our list!" ) - .arg( url.url() ).arg( episodeId ).arg( channelId ); - return TrackPtr(); + .arg( string ).arg( episodeId ).arg( channelId ); + return SqlPodcastEpisodePtr(); } Meta::SqlPodcastEpisodePtr episode; foreach( episode, channel->sqlEpisodes() ) - { if( episode->dbId() == episodeId ) - { - debug() << "found it!"; - return Meta::TrackPtr::dynamicCast( episode ); - } - } + return episode; //The episode was found in the database but it's channel didn't have it in it's list. //That probably is because it's beyond the purgecount limit. - episode = new Meta::SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ); + return SqlPodcastEpisodePtr( new SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ) ); +} + +bool +SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const +{ + SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); + if( !sqlStorage ) + return false; + + QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " + "OR localurl='%1';"; + command = command.arg( sqlStorage->escape( url.url() ) ); + + QStringList dbResult = sqlStorage->query( command ); + return !dbResult.isEmpty(); +} + +Meta::TrackPtr +SqlPodcastProvider::trackForUrl( const KUrl &url ) +{ + if( url.isEmpty() ) + return TrackPtr(); + + SqlPodcastEpisodePtr episode = sqlEpisodeForString( url.url() ); return Meta::TrackPtr::dynamicCast( episode ); } @@ -263,6 +260,12 @@ SqlPodcastProvider::playlists() return playlistList; } +Meta::PodcastEpisodePtr +SqlPodcastProvider::episodeForGuid( const QString &guid ) +{ + return PodcastEpisodePtr::dynamicCast( sqlEpisodeForString( guid ) ); +} + void SqlPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/podcasts/sql/SqlPodcastProvider.h b/src/podcasts/sql/SqlPodcastProvider.h index d45c968..0bfb20b 100644 --- a/src/podcasts/sql/SqlPodcastProvider.h +++ b/src/podcasts/sql/SqlPodcastProvider.h @@ -50,6 +50,8 @@ class SqlPodcastProvider : public PodcastProvider Meta::PlaylistList playlists(); //PodcastProvider methods + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + void addPodcast( const KUrl &url ); Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); @@ -114,9 +116,8 @@ class SqlPodcastProvider : public PodcastProvider void createTables() const; void loadPodcasts(); - /** return the url as a string. Removes percent encoding if it actually has a non-url guid. - */ - static QString cleanUrlOrGuid( const KUrl &url ); + /** @arg string: a url, localUrl or guid in string form */ + Meta::SqlPodcastEpisodePtr sqlEpisodeForString( const QString &string ); void updateDatabase( int fromVersion, int toVersion ); void fetchImage( Meta::SqlPodcastChannelPtr channel ); commit 839538ae580be93d4ab6260b3b3825ed584b02c2 Author: Bart Cerneels <bart.cerneels@kde.org> Date: Thu Mar 25 20:13:04 2010 +0100 Work around KUrl string parsing for guids. trackForUrl can not be used to query by guid because urls are not allowed to have non-latin characters, spaces, percent encoded entries, capitals, etc. So we'll use a function that doesn't take a KUrl. BUG:231230 diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp index 3a8ce5b..7700a16 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.cpp @@ -55,6 +55,13 @@ UmsPodcastProvider::trackForUrl( const KUrl &url ) return TrackPtr(); } +PodcastEpisodePtr +UmsPodcastProvider::episodeForGuid( const QString &guid ) +{ + Q_UNUSED( guid ) + return PodcastEpisodePtr(); +} + void UmsPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/collection/umscollection/podcasts/UmsPodcastProvider.h b/src/collection/umscollection/podcasts/UmsPodcastProvider.h index 059ed45..f052769 100644 --- a/src/collection/umscollection/podcasts/UmsPodcastProvider.h +++ b/src/collection/umscollection/podcasts/UmsPodcastProvider.h @@ -36,6 +36,8 @@ class UmsPodcastProvider : public PodcastProvider virtual bool possiblyContainsTrack( const KUrl &url ) const; virtual Meta::TrackPtr trackForUrl( const KUrl &url ); + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + virtual void addPodcast( const KUrl &url ); virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); diff --git a/src/podcasts/PodcastProvider.h b/src/podcasts/PodcastProvider.h index 6bda936..d670ec1 100644 --- a/src/podcasts/PodcastProvider.h +++ b/src/podcasts/PodcastProvider.h @@ -41,6 +41,14 @@ class AMAROK_EXPORT PodcastProvider : public Amarok::TrackProvider, public Playl virtual bool possiblyContainsTrack( const KUrl &url ) const = 0; virtual Meta::TrackPtr trackForUrl( const KUrl &url ) = 0; + /** Special function to get an episode for a given guid. + * + * note: this functions is required because KUrl does not preserve every possible guids. + * This means we can not use trackForUrl(). + * Problematic guids contain non-latin characters, percent encoded parts, capitals, etc. + */ + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ) = 0; + virtual void addPodcast( const KUrl &url ) = 0; virtual Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ) = 0; diff --git a/src/podcasts/PodcastReader.cpp b/src/podcasts/PodcastReader.cpp index f609222..1722bd8 100644 --- a/src/podcasts/PodcastReader.cpp +++ b/src/podcasts/PodcastReader.cpp @@ -1149,15 +1149,18 @@ PodcastReader::endItem() m_item->setDescription( description ); } + Meta::PodcastEpisodePtr episode; QString guid = m_item->guid(); - bool useGuid = !guid.isEmpty() && - !guid.contains( "[A-Z]" ) && //KUrl only uses lowercase - !guid.startsWith( '/' ); //appends file:// - - const KUrl trackId( useGuid ? m_item->guid() : m_item->uidUrl() ); - Meta::PodcastEpisodePtr episode = Meta::PodcastEpisodePtr::dynamicCast( - m_podcastProvider->trackForUrl( trackId ) + if( guid.isEmpty() ) + { + episode = Meta::PodcastEpisodePtr::dynamicCast( + m_podcastProvider->trackForUrl( m_item->uidUrl() ) ); + } + else + { + episode = m_podcastProvider->episodeForGuid( guid ); + } //make sure that the episode is not a bogus match. The channel has to be correct. // See http://bugs.kde.org/show_bug.cgi?id=227515 diff --git a/src/podcasts/sql/SqlPodcastProvider.cpp b/src/podcasts/sql/SqlPodcastProvider.cpp index fa11604..a805867 100644 --- a/src/podcasts/sql/SqlPodcastProvider.cpp +++ b/src/podcasts/sql/SqlPodcastProvider.cpp @@ -170,47 +170,25 @@ SqlPodcastProvider::loadPodcasts() emit( updated() ); } -QString -SqlPodcastProvider::cleanUrlOrGuid( const KUrl &url ) +SqlPodcastEpisodePtr +SqlPodcastProvider::sqlEpisodeForString( const QString &string ) { - QString decodedUrl = QUrl::fromPercentEncoding( url.url().toUtf8() ); - return decodedUrl; -} + if( string.isEmpty() ) + return SqlPodcastEpisodePtr(); -bool -SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const -{ SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); if( !sqlStorage ) - return false; - - QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " - "OR localurl='%1';"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); - - QStringList dbResult = sqlStorage->query( command ); - return !dbResult.isEmpty(); -} - -Meta::TrackPtr -SqlPodcastProvider::trackForUrl( const KUrl &url ) -{ - if( url.isEmpty() ) - return TrackPtr(); - - SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); - if( !sqlStorage ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); QString command = "SELECT id, url, channel, localurl, guid, " "title, subtitle, sequencenumber, description, mimetype, pubdate, " "duration, filesize, isnew FROM podcastepisodes " "WHERE guid='%1' OR url='%1' OR localurl='%1' ORDER BY id DESC;"; - command = command.arg( sqlStorage->escape( cleanUrlOrGuid( url ) ) ); + command = command.arg( sqlStorage->escape( string ) ); QStringList dbResult = sqlStorage->query( command ); if( dbResult.isEmpty() ) - return TrackPtr(); + return SqlPodcastEpisodePtr(); int episodeId = dbResult[0].toInt(); int channelId = dbResult[2].toInt(); @@ -229,23 +207,42 @@ SqlPodcastProvider::trackForUrl( const KUrl &url ) { error() << QString( "There is a track in the database with url/guid=%1 (%2) " "but there is no channel with dbId=%3 in our list!" ) - .arg( url.url() ).arg( episodeId ).arg( channelId ); - return TrackPtr(); + .arg( string ).arg( episodeId ).arg( channelId ); + return SqlPodcastEpisodePtr(); } Meta::SqlPodcastEpisodePtr episode; foreach( episode, channel->sqlEpisodes() ) - { if( episode->dbId() == episodeId ) - { - debug() << "found it!"; - return Meta::TrackPtr::dynamicCast( episode ); - } - } + return episode; //The episode was found in the database but it's channel didn't have it in it's list. //That probably is because it's beyond the purgecount limit. - episode = new Meta::SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ); + return SqlPodcastEpisodePtr( new SqlPodcastEpisode( dbResult.mid( 0, 14 ), channel ) ); +} + +bool +SqlPodcastProvider::possiblyContainsTrack( const KUrl &url ) const +{ + SqlStorage *sqlStorage = CollectionManager::instance()->sqlStorage(); + if( !sqlStorage ) + return false; + + QString command = "SELECT title FROM podcastepisodes WHERE guid='%1' OR url='%1' " + "OR localurl='%1';"; + command = command.arg( sqlStorage->escape( url.url() ) ); + + QStringList dbResult = sqlStorage->query( command ); + return !dbResult.isEmpty(); +} + +Meta::TrackPtr +SqlPodcastProvider::trackForUrl( const KUrl &url ) +{ + if( url.isEmpty() ) + return TrackPtr(); + + SqlPodcastEpisodePtr episode = sqlEpisodeForString( url.url() ); return Meta::TrackPtr::dynamicCast( episode ); } @@ -263,6 +260,12 @@ SqlPodcastProvider::playlists() return playlistList; } +Meta::PodcastEpisodePtr +SqlPodcastProvider::episodeForGuid( const QString &guid ) +{ + return PodcastEpisodePtr::dynamicCast( sqlEpisodeForString( guid ) ); +} + void SqlPodcastProvider::addPodcast( const KUrl &url ) { diff --git a/src/podcasts/sql/SqlPodcastProvider.h b/src/podcasts/sql/SqlPodcastProvider.h index d45c968..0bfb20b 100644 --- a/src/podcasts/sql/SqlPodcastProvider.h +++ b/src/podcasts/sql/SqlPodcastProvider.h @@ -50,6 +50,8 @@ class SqlPodcastProvider : public PodcastProvider Meta::PlaylistList playlists(); //PodcastProvider methods + virtual Meta::PodcastEpisodePtr episodeForGuid( const QString &guid ); + void addPodcast( const KUrl &url ); Meta::PodcastChannelPtr addChannel( Meta::PodcastChannelPtr channel ); @@ -114,9 +116,8 @@ class SqlPodcastProvider : public PodcastProvider void createTables() const; void loadPodcasts(); - /** return the url as a string. Removes percent encoding if it actually has a non-url guid. - */ - static QString cleanUrlOrGuid( const KUrl &url ); + /** @arg string: a url, localUrl or guid in string form */ + Meta::SqlPodcastEpisodePtr sqlEpisodeForString( const QString &string ); void updateDatabase( int fromVersion, int toVersion ); void fetchImage( Meta::SqlPodcastChannelPtr channel ); |