Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.kdev4/
audex.kdev4
build/

9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
configure_file(config.h.cmake ${CMAKE_BINARY_DIR}/config.h)

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fexceptions -Wall -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fexceptions")

include(KDEInstallDirs)
include(KDECMakeSettings)
Expand Down Expand Up @@ -58,6 +58,8 @@ set_package_properties(KF5Cddb PROPERTIES
PURPOSE "libkcddb is used to retrieve audio CD meta data from the internet."
)
find_package(Cdparanoia REQUIRED)
find_package(MusicBrainz REQUIRED)
find_package(CoverArt REQUIRED)

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
Expand Down Expand Up @@ -92,6 +94,7 @@ set(audex_SRCS
utils/cuesheetwriter.cpp
utils/tmpdir.cpp
utils/discidcalculator.cpp
utils/musicbrainzjob.cpp
widgets/cddaheaderwidget.cpp
widgets/generalsettingswidget.cpp
widgets/devicewidget.cpp
Expand Down Expand Up @@ -168,6 +171,8 @@ target_link_libraries(audex
KF5::XmlGui
KF5::Cddb
${CDPARANOIA_LIBRARIES}
${MUSICBRAINZ_LIBRARIES}
${COVERART_LIBRARIES}
)

install(TARGETS audex DESTINATION ${BIN_INSTALL_DIR})
Expand Down
2 changes: 1 addition & 1 deletion audex.kcfg
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<default>true</default>
</entry>
<entry name="coverLookupAuto" type="Bool">
<label>Perform cover lookup (amazon) automatically</label>
<label>Perform cover lookup (MusicBrainz) automatically</label>
<default>true</default>
</entry>
<entry name="wikipediaLocale" type="Int">
Expand Down
29 changes: 29 additions & 0 deletions cmake/modules/FindCoverArt.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# - Try to find the CoverArt library
# Once done this will define
#
# COVERART_FOUND - system has CoverArt
# COVERART_INCLUDE_DIR - the CoverArt include directory
# COVERART_LIBRARIES - Link these to use CoverArt
#

if (COVERART_INCLUDE_DIR AND COVERART_LIBRARIES)
# in cache already
SET(COVERART_FOUND TRUE)

else (COVERART_INCLUDE_DIR AND COVERART_LIBRARIES)

FIND_PATH(COVERART_INCLUDE_DIR coverart/caa_c.h)

FIND_LIBRARY(COVERART_LIBRARY coverartcc)

IF (COVERART_LIBRARY)
SET(COVERART_LIBRARIES ${COVERART_LIBRARY} "-lm")
ENDIF (COVERART_LIBRARY)

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CoverArt DEFAULT_MSG
COVERART_LIBRARIES COVERART_INCLUDE_DIR)

MARK_AS_ADVANCED(COVERART_INCLUDE_DIR COVERART_LIBRARIES)

endif (COVERART_INCLUDE_DIR AND COVERART_LIBRARIES)
29 changes: 29 additions & 0 deletions cmake/modules/FindMusicBrainz.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# - Try to find the MusicBrainz library
# Once done this will define
#
# MUSICBRAINZ_FOUND - system has MusicBrainz
# MUSICBRAINZ_INCLUDE_DIR - the MusicBrainz include directory
# MUSICBRAINZ_LIBRARIES - Link these to use MusicBrainz
#

if (MUSICBRAINZ_INCLUDE_DIR AND MUSICBRAINZ_LIBRARIES)
# in cache already
SET(MUSICBRAINZ_FOUND TRUE)

else (MUSICBRAINZ_INCLUDE_DIR AND MUSICBRAINZ_LIBRARIES)

FIND_PATH(MUSICBRAINZ_INCLUDE_DIR musicbrainz5/mb5_c.h)

FIND_LIBRARY(MUSICBRAINZ_LIBRARY musicbrainz5cc)

IF (MUSICBRAINZ_LIBRARY)
SET(MUSICBRAINZ_LIBRARIES ${MUSICBRAINZ_LIBRARY} "-lm")
ENDIF (MUSICBRAINZ_LIBRARY)

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MusicBrainz DEFAULT_MSG
MUSICBRAINZ_LIBRARIES MUSICBRAINZ_INCLUDE_DIR)

MARK_AS_ADVANCED(MUSICBRAINZ_INCLUDE_DIR MUSICBRAINZ_LIBRARIES)

endif (MUSICBRAINZ_INCLUDE_DIR AND MUSICBRAINZ_LIBRARIES)
8 changes: 4 additions & 4 deletions dialogs/coverbrowserdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ CoverBrowserDialog::~CoverBrowserDialog() {

}

void CoverBrowserDialog::fetchThumbnails(const QString& searchstring, const int fetchCount) {
void CoverBrowserDialog::fetchThumbnails(const QString& searchArtist, const QString& searchAlbum, const int fetchCount) {
if (fetchCount == 0)
cover_fetcher.startFetchThumbnails(searchstring, Preferences::fetchCount());
cover_fetcher.startFetchThumbnails(searchArtist, searchAlbum, Preferences::fetchCount());
else
cover_fetcher.startFetchThumbnails(searchstring, fetchCount);
cover_fetcher.startFetchThumbnails(searchArtist, searchAlbum, fetchCount);
ui.label->setText(i18n("Searching for covers..."));
}

Expand Down Expand Up @@ -97,7 +97,7 @@ void CoverBrowserDialog::setup() {
static const int constIconSize=128;


setWindowTitle(i18n("Fetch Cover From Google"));
setWindowTitle(i18n("Fetch Cover From MusicBrainz"));

QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
Expand Down
2 changes: 1 addition & 1 deletion dialogs/coverbrowserdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class CoverBrowserDialog : public QDialog {
inline int count() { return cover_fetcher.count(); }

public slots:
void fetchThumbnails(const QString& searchstring, const int fetchCount = 0);
void fetchThumbnails(const QString& searchArtist, const QString& searchAlbum, const int fetchCount = 0);
void startFetchCover(const int no);

signals:
Expand Down
2 changes: 1 addition & 1 deletion mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ void MainWindow::cddb_lookup_done(const bool successful) {
}
update_layout();
disable_submit();
if (Preferences::coverLookupAuto()) cdda_header_widget->googleAuto();
if (Preferences::coverLookupAuto()) cdda_header_widget->musicBrainzAuto();
}

void MainWindow::update_layout() {
Expand Down
136 changes: 42 additions & 94 deletions utils/coverfetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include "coverfetcher.h"
#include "musicbrainzjob.h"
#include <algorithm>
#include <QDebug>
#include <QScriptEngine>
Expand All @@ -38,60 +39,53 @@ CoverFetcher::~CoverFetcher() {
clear();
}

void CoverFetcher::fetched_external_ip(KJob* job) {
void CoverFetcher::startFetchThumbnails(const QString& searchArtist, const QString& searchAlbum, const int fetchNo) {

qDebug() << "got IP...";
if (!job) {
qDebug() << "no job error ...";
emit nothingFetched();
return;
} else if (job && job->error()) {
qDebug() << "reply error ...";
emit nothingFetched();
return;
qDebug() << "Fetch Thumbs ...";
if (_status != NOS || fetchNo == 0)
{
emit nothingFetched();
return;
}
// http://www.telize.com/ip returns plaintext ip address
KIO::StoredTransferJob* const storedJob = static_cast<KIO::StoredTransferJob*>(job);
external_ip = ((QString) storedJob->data()).trimmed();

qDebug() << "IP " << external_ip;

// Max images per request on Google API is 8, thus the std::min
QString url;
url= QString("https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=%1&rsz=%2&userip=%3")
.arg(QUrl::toPercentEncoding(search_string, "/").data())
.arg(std::min(fetch_no,8))
.arg(QUrl::toPercentEncoding(external_ip).data());

qDebug() << "searching covers (" << url << ")...";
fetch_no = fetchNo;

_status = SEARCHING;
emit statusChanged(SEARCHING);

job = KIO::storedGet(url);
connect(job, SIGNAL(result(KJob*)), SLOT(fetched_html_data(KJob*)));

musicbrainz_job = new MusicBrainzJob(searchArtist, searchAlbum, fetchNo);
connect(musicbrainz_job, SIGNAL(finished()), SLOT(fetched_musicbrainz_cover_art_urls()));
musicbrainz_job->fetchCoverArtURLs();

}

void CoverFetcher::startFetchThumbnails(const QString& searchstring, const int fetchNo) {
void CoverFetcher::fetched_musicbrainz_cover_art_urls() {

qDebug() << "Fetch Thumbs ...";
if (_status != NOS || fetchNo == 0)
{
emit nothingFetched();
return;
}
switch (_status) {

fetch_no = fetchNo;
case SEARCHING : {
qDebug() << "searching finished.";

QMap<QString, QString>::iterator it;

int cover_name = 0;

for (it = musicbrainz_job->cover_art_urls.begin(); it != musicbrainz_job->cover_art_urls.end(); it++)
{
cover_urls_thumbnails << it.key();
cover_urls << it.value();
cover_name++;
cover_names << QString::number(cover_name);
}

search_string = searchstring;
search_string.replace("&", "");
_status = NOS; emit statusChanged(NOS);
fetch_cover_thumbnail();
} break;

// Google requires the user IP
QString url("http://www.telize.com/ip");
case NOS : break;

job = KIO::storedGet(url);
connect(job, SIGNAL(result(KJob*)), SLOT(fetched_external_ip(KJob*)));
default : break;
}

}

Expand All @@ -105,6 +99,7 @@ void CoverFetcher::stopFetchThumbnails() {

}


void CoverFetcher::startFetchCover(const int no) {

if (_status != NOS) return;
Expand Down Expand Up @@ -137,8 +132,8 @@ void CoverFetcher::fetched_html_data(KJob* job) {
QByteArray buffer;

if (job && job->error()) {
qDebug() << "There was an error communicating with Google. "<< job->errorString();
emit error(i18n("There was an error communicating with Google."), i18n("Try again later. Otherwise make a bug report."));
qDebug() << "There was an error communicating with MusicBrainz. "<< job->errorString();
emit error(i18n("There was an error communicating with MusicBrainz."), i18n("Try again later. Otherwise make a bug report."));
_status = NOS; emit statusChanged(NOS);
emit nothingFetched();
return;
Expand All @@ -149,23 +144,15 @@ void CoverFetcher::fetched_html_data(KJob* job) {
}

if (buffer.count() == 0) {
qDebug() << "Google server: empty response";
emit error(i18n("Google server: Empty response."),
qDebug() << "MusicBrainz server: empty response";
emit error(i18n("MusicBrainz server: Empty response."),
i18n("Try again later. Make a bug report."));
_status = NOS; emit statusChanged(NOS);
return;
}

switch (_status) {

case SEARCHING : {
qDebug() << "searching finished.";
//qDebug() << QString::fromUtf8(buffer.data());
parse_html_response(QString::fromUtf8(buffer.data()));
_status = NOS; emit statusChanged(NOS);
fetch_cover_thumbnail();
} break;

case FETCHING_THUMBNAIL : {
qDebug() << "cover thumbnail fetched.";
cover_thumbnails.append(buffer);
Expand All @@ -182,58 +169,19 @@ void CoverFetcher::fetched_html_data(KJob* job) {

case FETCHING_COVER : {
qDebug() << "cover fetched.";
_status = NOS; emit statusChanged(NOS);
_status = NOS; emit statusChanged(NOS);
emit fetchedCover(buffer);
} break;

case NOS : break;

default : break;

}


}

void CoverFetcher::parse_html_response(const QString& xml) {

cover_urls_thumbnails.clear();
cover_urls.clear();
cover_names.clear();
cover_tbnids.clear();
cover_thumbnails.clear();

QScriptValue responseData;
QScriptEngine engine;
responseData = engine.evaluate("("+xml+")");


QScriptValue resultsData=responseData.property("responseData").property("results");

if (resultsData.isArray()) {

QScriptValueIterator it(resultsData);

while (it.hasNext()) {

it.next();
if (it.flags() & QScriptValue::SkipInEnumeration) continue;

QScriptValue entry = it.value();

QString link = QUrl::fromPercentEncoding(entry.property("url").toString().toAscii());
QString thumbUrl = QUrl::fromPercentEncoding(entry.property("tbUrl").toString().toAscii());
QString w = entry.property("width").toString();
QString h = entry.property("height").toString();

cover_urls << link;
cover_names << i18n("%1x%2", w, h);
cover_urls_thumbnails << thumbUrl;

qDebug() << "URL " << link << "- " << thumbUrl<< " -"<<cover_names;

}

}
}

bool CoverFetcher::fetch_cover_thumbnail() {

Expand Down
Loading