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