1 /*
2     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
3     SPDX-License-Identifier: GPL-2.0-or-later
4 */
5 
6 #include "k3bmusicbrainzjob.h"
7 #include "k3bmusicbrainztrackloopupjob.h"
8 
9 #include "k3baudiotrack.h"
10 #include "k3baudiodatasource.h"
11 #include "k3bsimplejobhandler.h"
12 
13 #include <KLocalizedString>
14 #include <KMessageBox>
15 
16 #include <QInputDialog>
17 
18 
19 class K3b::MusicBrainzJob::Private
20 {
21 public:
22     QList<K3b::AudioTrack*> tracks;
23     int currentTrackIndex;
24     bool canceled;
25     K3b::MusicBrainzTrackLookupJob* mbTrackLookupJob;
26 };
27 
28 
29 // cannot use this as parent for the K3b::SimpleJobHandler since this has not been constructed yet
MusicBrainzJob(QWidget * parent)30 K3b::MusicBrainzJob::MusicBrainzJob( QWidget* parent )
31     : K3b::Job( new K3b::SimpleJobHandler( 0 ), parent ),
32       d( new Private() )
33 {
34     d->canceled = false;
35     d->mbTrackLookupJob = new K3b::MusicBrainzTrackLookupJob( this, this );
36 
37     connect( d->mbTrackLookupJob, SIGNAL(percent(int)), this, SIGNAL(subPercent(int)), Qt::QueuedConnection );
38     connect( d->mbTrackLookupJob, SIGNAL(percent(int)), this, SLOT(slotTrmPercent(int)), Qt::QueuedConnection );
39     connect( d->mbTrackLookupJob, SIGNAL(finished(bool)), this, SLOT(slotMbJobFinished(bool)), Qt::QueuedConnection );
40     connect( d->mbTrackLookupJob, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)), Qt::QueuedConnection );
41 }
42 
43 
~MusicBrainzJob()44 K3b::MusicBrainzJob::~MusicBrainzJob()
45 {
46     delete jobHandler();
47     delete d;
48 }
49 
50 
hasBeenCanceled() const51 bool K3b::MusicBrainzJob::hasBeenCanceled() const
52 {
53     return d->canceled;
54 }
55 
56 
setTracks(const QList<K3b::AudioTrack * > & tracks)57 void K3b::MusicBrainzJob::setTracks( const QList<K3b::AudioTrack*>& tracks )
58 {
59     d->tracks = tracks;
60 }
61 
62 
start()63 void K3b::MusicBrainzJob::start()
64 {
65     jobStarted();
66 
67     d->canceled = false;
68     d->currentTrackIndex = 0;
69 
70     d->mbTrackLookupJob->setAudioTrack( d->tracks.first() );
71     d->mbTrackLookupJob->start();
72 }
73 
74 
cancel()75 void K3b::MusicBrainzJob::cancel()
76 {
77     d->canceled = true;
78     d->mbTrackLookupJob->cancel();
79 }
80 
81 
slotTrmPercent(int p)82 void K3b::MusicBrainzJob::slotTrmPercent( int p )
83 {
84     // the easy way (inaccurate)
85     emit percent( (100*d->currentTrackIndex + p) / d->tracks.count() );
86 }
87 
88 
slotMbJobFinished(bool success)89 void K3b::MusicBrainzJob::slotMbJobFinished( bool success )
90 {
91     if( hasBeenCanceled() ) {
92         emit canceled();
93         jobFinished(false);
94     }
95     else {
96         K3b::AudioTrack* currentTrack = d->tracks.at( d->currentTrackIndex );
97 
98         if( success ) {
99             // found entries
100             QStringList resultStrings, resultStringsUnique;
101             for( int i = 0; i < d->mbTrackLookupJob->results(); ++i )
102                 resultStrings.append( d->mbTrackLookupJob->artist(i) + " - " + d->mbTrackLookupJob->title(i) );
103 
104             // since we are only using the title and the artist a lot of entries are alike to us
105             // so to not let the user have to choose between two equal entries we trim the list down
106             for( QStringList::const_iterator it = resultStrings.constBegin();
107                  it != resultStrings.constEnd(); ++it )
108                 if( !resultStringsUnique.contains( *it ) )
109                     resultStringsUnique.append( *it );
110 
111             QString s;
112             bool ok = true;
113             if( resultStringsUnique.count() > 1 )
114                 s = QInputDialog::getItem( dynamic_cast<QWidget*>(parent()),
115                                            i18n("MusicBrainz Query"),
116                                            i18n("Found multiple matches for track %1 (%2). Please select one.",
117                                                 currentTrack->trackNumber(),
118                                                 currentTrack->firstSource()->sourceComment()),
119                                            resultStringsUnique,
120                                            0,
121                                            false,
122                                            &ok );
123             else
124                 s = resultStringsUnique.first();
125 
126             if( ok ) {
127                 int i = resultStrings.lastIndexOf( s );
128                 currentTrack->setTitle( d->mbTrackLookupJob->title(i) );
129                 currentTrack->setArtist( d->mbTrackLookupJob->artist(i) );
130             }
131         }
132 
133         emit trackFinished( currentTrack, success );
134 
135         // query next track
136         ++d->currentTrackIndex;
137         if( d->currentTrackIndex < d->tracks.count() ) {
138             d->mbTrackLookupJob->setAudioTrack( d->tracks.at( d->currentTrackIndex ) );
139             d->mbTrackLookupJob->start();
140         }
141         else {
142             jobFinished( true );
143         }
144     }
145 }
146 
147 
148