1 /****************************************************************************************
2 * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify it under *
5 * the terms of the GNU General Public License as published by the Free Software *
6 * Foundation; either version 2 of the License, or (at your option) any later *
7 * version. *
8 * *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
12 * *
13 * You should have received a copy of the GNU General Public License along with *
14 * this program. If not, see <http://www.gnu.org/licenses/>. *
15 ****************************************************************************************/
16
17 #include "AmpacheServiceCollection.h"
18
19 #include "AmpacheServiceQueryMaker.h"
20 #include "NetworkAccessManagerProxy.h"
21
22 #include <KLocalizedString>
23 #include <ThreadWeaver/ThreadWeaver>
24 #include <ThreadWeaver/Queue>
25
26 #include <QDomDocument>
27 #include <QNetworkReply>
28 #include <QUrlQuery>
29
30 using namespace Collections;
31
AmpacheServiceCollection(ServiceBase * service,const QUrl & server,const QString & sessionId)32 AmpacheServiceCollection::AmpacheServiceCollection( ServiceBase *service,
33 const QUrl &server,
34 const QString &sessionId )
35 : ServiceCollection( service, "AmpacheCollection", "AmpacheCollection" )
36 , m_server( server )
37 , m_sessionId( sessionId )
38 {
39 m_trackForUrlWorker = nullptr;
40 }
41
~AmpacheServiceCollection()42 AmpacheServiceCollection::~AmpacheServiceCollection()
43 {
44 }
45
46 QueryMaker *
queryMaker()47 AmpacheServiceCollection::queryMaker()
48 {
49 return new AmpacheServiceQueryMaker( this, m_server, m_sessionId );
50 }
51
52 QString
collectionId() const53 AmpacheServiceCollection::collectionId() const
54 {
55 return "Ampache: " + m_server.url();
56 }
57
58 QString
prettyName() const59 AmpacheServiceCollection::prettyName() const
60 {
61 return i18n( "Ampache Server %1", m_server.url() );
62 }
63
64 bool
possiblyContainsTrack(const QUrl & url) const65 AmpacheServiceCollection::possiblyContainsTrack( const QUrl &url ) const
66 {
67 return m_server.isParentOf( url );
68 }
69
70 void
slotAuthenticationNeeded()71 AmpacheServiceCollection::slotAuthenticationNeeded()
72 {
73 Q_EMIT authenticationNeeded();
74 }
75
76 Meta::TrackPtr
trackForUrl(const QUrl & url)77 AmpacheServiceCollection::trackForUrl( const QUrl &url )
78 {
79 MetaProxy::TrackPtr trackptr( new MetaProxy::Track( url, MetaProxy::Track::ManualLookup ) );
80 AmpacheTrackForUrlWorker *worker = new AmpacheTrackForUrlWorker( url, trackptr,
81 m_server, m_sessionId, service() );
82 connect( worker, &AmpacheTrackForUrlWorker::authenticationNeeded,
83 this, &AmpacheServiceCollection::slotAuthenticationNeeded );
84 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(worker) );
85
86 return Meta::TrackPtr::staticCast( trackptr );
87 }
88
slotLookupComplete(const Meta::TrackPtr &)89 void AmpacheServiceCollection::slotLookupComplete( const Meta::TrackPtr& )
90 {
91 }
92
parseTrack(const QString & xml)93 void AmpacheTrackForUrlWorker::parseTrack( const QString &xml )
94 {
95 //so lets figure out what we got here:
96 QDomDocument doc( "reply" );
97 doc.setContent( xml );
98 QDomElement root = doc.firstChildElement( "root" );
99 QDomElement song = root.firstChildElement( "song" );
100
101 m_urlTrackId = song.attribute( "id", "0" ).toInt();
102
103 QDomElement element = song.firstChildElement( "title" );
104
105 QString title = element.text();
106 if ( title.isEmpty() ) title = "Unknown";
107
108 element = song.firstChildElement( "url" );
109
110 m_urlTrack = new Meta::AmpacheTrack( title, m_service );
111 Meta::TrackPtr trackPtr( m_urlTrack );
112
113 m_urlTrack->setUidUrl( element.text() );
114 m_urlTrack->setId( m_urlTrackId );
115
116 element = song.firstChildElement( "time" );
117 m_urlTrack->setLength( element.text().toInt() * 1000 );
118
119 element = song.firstChildElement( "track" );
120 m_urlTrack->setTrackNumber( element.text().toInt() );
121
122 QDomElement albumElement = song.firstChildElement( "album" );
123 m_urlAlbumId = albumElement.attribute( "id", "0" ).toInt();
124
125 Meta::AmpacheAlbum *album = new Meta::AmpacheAlbum( albumElement.text() );
126
127 QDomElement artElement = song.firstChildElement( "art" );
128 album->setCoverUrl( artElement.text() );
129
130 album->addTrack( trackPtr );
131 m_urlTrack->setAlbumPtr( Meta::AlbumPtr( album ) );
132
133 QDomElement artistElement = song.firstChildElement( "artist" );
134 Meta::ServiceArtist *artist = new Meta::ServiceArtist( artistElement.text() );
135
136 Meta::ArtistPtr artistPtr( artist );
137 m_urlTrack->setArtist( artistPtr );
138 album->setAlbumArtist( artistPtr );
139 }
140
AmpacheTrackForUrlWorker(const QUrl & url,const MetaProxy::TrackPtr & track,const QUrl & server,const QString & sessionId,ServiceBase * service)141 AmpacheTrackForUrlWorker::AmpacheTrackForUrlWorker( const QUrl &url,
142 const MetaProxy::TrackPtr &track,
143 const QUrl &server,
144 const QString &sessionId,
145 ServiceBase *service )
146 : Amarok::TrackForUrlWorker( url )
147 , m_proxy( track )
148 , m_server( server )
149 , m_sessionId( sessionId )
150 , m_service( service )
151 {
152 }
153
~AmpacheTrackForUrlWorker()154 AmpacheTrackForUrlWorker::~AmpacheTrackForUrlWorker()
155 {}
156
157 void
run(ThreadWeaver::JobPointer self,ThreadWeaver::Thread * thread)158 AmpacheTrackForUrlWorker::run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread)
159 {
160 Q_UNUSED( self )
161 Q_UNUSED( thread )
162
163 m_urlTrack = nullptr;
164 m_urlAlbum = nullptr;
165 m_urlArtist = nullptr;
166
167 m_urlTrackId = 0;
168 m_urlAlbumId = 0;
169 m_urlArtistId = 0;
170
171 //send url_to_song to Ampache
172
173 QUrl requestUrl = m_server;
174 requestUrl.setPath( m_server.path() + QStringLiteral("/server/xml.server.php") );
175 QUrlQuery query;
176 query.addQueryItem( "action", "url_to_song" );
177 query.addQueryItem( "auth", m_sessionId );
178 query.addQueryItem( "url", m_url.toEncoded() );
179 requestUrl.setQuery( query );
180
181 QNetworkRequest req( requestUrl );
182 QNetworkReply *reply = The::networkAccessManager()->get( req );
183
184 if( reply->waitForReadyRead(-1) )
185 {
186 if( reply->error() == QNetworkReply::ContentAccessDenied )
187 {
188 debug() << "Trying to re-authenticate Ampache..";
189 Q_EMIT authenticationNeeded();
190 }
191 }
192 parseTrack( reply->readAll() );
193 m_track = Meta::TrackPtr( m_urlTrack );
194 m_proxy->updateTrack( m_track );
195 reply->deleteLater();
196 }
197