File indexing completed on 2024-05-19 04:49:59
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "SqlPlaylist.h" 0018 0019 #include <core/storage/SqlStorage.h> 0020 #include "core/support/Debug.h" 0021 #include "core-impl/storage/StorageManager.h" 0022 #include "core-impl/meta/proxy/MetaProxy.h" 0023 #include "core-impl/meta/stream/Stream.h" 0024 #include "core-impl/meta/timecode/TimecodeMeta.h" 0025 #include "playlistmanager/PlaylistManager.h" 0026 #include "playlistmanager/sql/SqlPlaylistGroup.h" 0027 #include "playlistmanager/sql/SqlUserPlaylistProvider.h" 0028 0029 #include <typeinfo> 0030 0031 namespace Playlists { 0032 0033 SqlPlaylist::SqlPlaylist( const QString & name, const Meta::TrackList 0034 &tracks, SqlPlaylistGroupPtr parent, PlaylistProvider *provider, 0035 const QString &urlId ) 0036 : m_dbId( -1 ) 0037 , m_parent( parent ) 0038 , m_tracks( tracks ) 0039 , m_provider( provider) 0040 , m_name( name ) 0041 , m_urlId( urlId ) 0042 , m_tracksLoaded( true ) 0043 { 0044 saveToDb(); 0045 } 0046 0047 SqlPlaylist::SqlPlaylist( const QStringList & resultRow, 0048 SqlPlaylistGroupPtr parent, 0049 PlaylistProvider *provider ) 0050 : m_parent( parent ) 0051 , m_provider( provider) 0052 , m_tracksLoaded( false ) 0053 { 0054 m_dbId = resultRow[0].toInt(); 0055 m_name = resultRow[2]; 0056 m_urlId = resultRow[3]; 0057 } 0058 0059 0060 SqlPlaylist::~SqlPlaylist() 0061 { 0062 } 0063 0064 QUrl 0065 SqlPlaylist::uidUrl() const 0066 { 0067 return QUrl( QStringLiteral( "amarok-sqlplaylistuid://%1").arg( m_dbId ) ); 0068 } 0069 0070 QStringList 0071 SqlPlaylist::groups() 0072 { 0073 QStringList groups; 0074 if( m_parent && !m_parent->name().isNull() ) 0075 groups << m_parent->name(); 0076 return groups; 0077 } 0078 0079 void 0080 SqlPlaylist::setGroups( const QStringList &groups ) 0081 { 0082 SqlUserPlaylistProvider *userPlaylistProvider = 0083 dynamic_cast<SqlUserPlaylistProvider *>( m_provider ); 0084 if( !userPlaylistProvider ) 0085 { 0086 error() << "Provider could not be cast to SqlUserPlaylistProvider"; 0087 return; 0088 } 0089 0090 if( groups.isEmpty() ) 0091 m_parent = SqlPlaylistGroupPtr(); 0092 else 0093 m_parent = userPlaylistProvider->group( groups.first() ); 0094 0095 saveToDb(); 0096 } 0097 0098 bool 0099 SqlPlaylist::saveToDb( bool tracks ) 0100 { 0101 int parentId = -1; 0102 if( m_parent ) 0103 parentId = m_parent->id(); 0104 0105 auto sql = StorageManager::instance()->sqlStorage(); 0106 0107 //figure out if we have a urlId and if this id is already in the db, if so, update it instead of creating a new one. 0108 if( !m_urlId.isEmpty() ) 0109 { 0110 debug() << "Checking " << m_urlId << " against db"; 0111 0112 //check if urlId exists 0113 QString query = QStringLiteral("SELECT id from playlists WHERE urlid='%1'"); 0114 query = query.arg( sql->escape( m_urlId ) ); 0115 QStringList result = sql->query( query ); 0116 0117 if( !result.isEmpty() ) 0118 { 0119 //set this id to the already existing one 0120 m_dbId = result.at( 0 ).toInt(); 0121 debug() << "Got existing playlist with id " << m_dbId; 0122 } 0123 } 0124 0125 if( m_dbId != -1 ) 0126 { 0127 //update existing 0128 QString query = QStringLiteral("UPDATE playlists SET parent_id=%1, name='%2' WHERE id=%3;"); 0129 query = query.arg( QString::number( parentId ), 0130 sql->escape( m_name ), 0131 QString::number( m_dbId ) ); 0132 StorageManager::instance()->sqlStorage()->query( query ); 0133 0134 if( tracks ) 0135 { 0136 //delete existing tracks and insert all 0137 query = QStringLiteral("DELETE FROM playlist_tracks where playlist_id=%1;"); 0138 query = query.arg( QString::number( m_dbId ) ); 0139 StorageManager::instance()->sqlStorage()->query( query ); 0140 saveTracks(); 0141 } 0142 } 0143 else 0144 { 0145 //insert new 0146 QString query = "INSERT INTO playlists ( parent_id, name, urlid ) " 0147 "VALUES ( %1, '%2', '%3' );"; 0148 query = query.arg( QString::number( parentId ), 0149 sql->escape( m_name ), 0150 sql->escape( m_urlId ) ); 0151 m_dbId = StorageManager::instance()->sqlStorage()->insert( query, QStringLiteral("playlists") ); 0152 if( tracks ) 0153 saveTracks(); 0154 } 0155 0156 //HACK! if this has just been added from the collection scanner, the list is full of "dirty" 0157 //tracks that might not all have been properly trackForUrl'ed, so clear the track list so we 0158 //reload if we ever need them! 0159 if( !m_urlId.isEmpty() ) 0160 { 0161 m_tracks.clear(); 0162 m_tracksLoaded = false; 0163 } 0164 0165 //clean the cache 0166 if( m_parent ) 0167 m_parent->clear(); 0168 0169 return true; 0170 } 0171 0172 void 0173 SqlPlaylist::saveTracks() 0174 { 0175 int trackNum = 1; 0176 auto sql = StorageManager::instance()->sqlStorage(); 0177 0178 foreach( Meta::TrackPtr trackPtr, m_tracks ) 0179 { 0180 if( trackPtr ) 0181 { 0182 // keep this in sync with SqlTrack::updatePlaylistsToDb()! 0183 debug() << "saving track with url " << trackPtr->uidUrl(); 0184 QString query = "INSERT INTO playlist_tracks ( playlist_id, track_num, url, title, " 0185 "album, artist, length, uniqueid ) VALUES ( %1, %2, '%3', '%4', '%5', " 0186 "'%6', %7, '%8' );"; 0187 query = query.arg( QString::number( m_dbId ), QString::number( trackNum ), 0188 sql->escape( trackPtr->uidUrl() ), 0189 sql->escape( trackPtr->prettyName() ), 0190 trackPtr->album() ? sql->escape( trackPtr->album()->prettyName() ) : QLatin1String(""), 0191 trackPtr->artist()? sql->escape( trackPtr->artist()->prettyName() ) : QLatin1String(""), 0192 QString::number( trackPtr->length() ), 0193 sql->escape( trackPtr->uidUrl() ) ); 0194 sql->insert( query, QStringLiteral("playlist_tracks") ); 0195 0196 trackNum++; 0197 } 0198 } 0199 } 0200 0201 int 0202 SqlPlaylist::trackCount() const 0203 { 0204 if( m_tracksLoaded ) 0205 return m_tracks.count(); 0206 else 0207 return -1; 0208 } 0209 0210 Meta::TrackList 0211 SqlPlaylist::tracks() 0212 { 0213 return m_tracks; 0214 } 0215 0216 void 0217 SqlPlaylist::triggerTrackLoad() 0218 { 0219 if( !m_tracksLoaded ) 0220 loadTracks(); 0221 notifyObserversTracksLoaded(); 0222 } 0223 0224 void 0225 SqlPlaylist::addTrack(const Meta::TrackPtr &track, int position ) 0226 { 0227 if( !m_tracksLoaded ) 0228 loadTracks(); 0229 0230 if( position < 0 ) 0231 position = m_tracks.count(); 0232 else 0233 position = qMin( position, m_tracks.count() ); 0234 m_tracks.insert( position, track ); 0235 saveToDb( true ); 0236 notifyObserversTrackAdded( track, position ); 0237 } 0238 0239 void 0240 SqlPlaylist::removeTrack( int position ) 0241 { 0242 if( !m_tracksLoaded ) 0243 loadTracks(); 0244 0245 if( position < 0 || position >= m_tracks.size() ) 0246 return; 0247 Meta::TrackPtr track = m_tracks.takeAt( position ); 0248 saveToDb( true ); 0249 notifyObserversTrackRemoved( position ); 0250 } 0251 0252 void 0253 SqlPlaylist::loadTracks() 0254 { 0255 QString query = "SELECT playlist_id, track_num, url, title, album, artist, length FROM " 0256 "playlist_tracks WHERE playlist_id=%1 ORDER BY track_num"; 0257 query = query.arg( QString::number( m_dbId ) ); 0258 0259 QStringList result = StorageManager::instance()->sqlStorage()->query( query ); 0260 0261 int resultRows = result.count() / 7; 0262 0263 for( int i = 0; i < resultRows; i++ ) 0264 { 0265 QStringList row = result.mid( i*7, 7 ); 0266 QUrl url = QUrl( row[2] ); 0267 0268 MetaProxy::TrackPtr proxyTrack( new MetaProxy::Track( url ) ); 0269 0270 proxyTrack->setTitle( row[3] ); 0271 proxyTrack->setAlbum( row[4] ); 0272 proxyTrack->setArtist( row[5] ); 0273 m_tracks << Meta::TrackPtr( proxyTrack.data() ); 0274 } 0275 0276 m_tracksLoaded = true; 0277 } 0278 0279 void 0280 SqlPlaylist::setName( const QString &name ) 0281 { 0282 m_name = name; 0283 saveToDb( false ); //no need to resave all tracks 0284 } 0285 0286 void 0287 SqlPlaylist::removeFromDb() 0288 { 0289 QString query = QStringLiteral("DELETE FROM playlist_tracks WHERE playlist_id=%1"); 0290 query = query.arg( QString::number( m_dbId ) ); 0291 StorageManager::instance()->sqlStorage()->query( query ); 0292 0293 query = QStringLiteral("DELETE FROM playlists WHERE id=%1"); 0294 query = query.arg( QString::number( m_dbId ) ); 0295 StorageManager::instance()->sqlStorage()->query( query ); 0296 } 0297 0298 } //namespace Playlists