/***************************************************************************
 *   Copyright (C) 2005 by Roland Weigert   *
 *   roweigert@t-online.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "musicbrainz-interface.h"

musicbrainzconnect::musicbrainzconnect()
{
    //New testcode for XML
    fetchedalbums=new QPtrList<musicbrainzalbum>;
    fetchedalbums->setAutoDelete(TRUE);
    url=new QHttp();
    url->setHost("musicbrainz.org",80);
    notfinished=TRUE;
    queryOk=FALSE;
    transactionid=0;
}

musicbrainzconnect::~musicbrainzconnect()
{
    delete url;
    delete fetchedalbums;
}

QByteArray musicbrainzconnect::musicbrainzquery(QString query)
{
    //First of all check, if this was already asked for.
    //So we never check the same thing twice, if it has no result
    //Give back the empty qbytearray, if this happens
    bool alreadychecked=FALSE;
    QStringList::Iterator queryiterator=querystrings.begin();
    while(queryiterator!=querystrings.end())
    {
        if(!(*queryiterator).compare(query))
            alreadychecked=TRUE;
        queryiterator++;
    }
    QByteArray receiveddata;
    if(!alreadychecked)
    {
        querystrings.append(query.lower());
        transactionid=url->get
                      (query);
        connect(url,SIGNAL(requestFinished (int, bool)),SLOT(getfinished(int,bool)));
        notfinished=TRUE;
        while (notfinished)
        {
            kapp->processEvents();
        }
        disconnect(url,SIGNAL(requestFinished (int, bool)),this,SLOT(getfinished(int,bool)));
        if (queryOk)
            receiveddata=url->readAll();
    }
    return receiveddata;
}

bool musicbrainzconnect::checkdouble(QString albumid)
{
    bool alreadyinlist=FALSE;
    QPtrList<musicbrainzalbum>::Iterator albumiterator=fetchedalbums->begin();
    while (albumiterator!=fetchedalbums->end()&&!alreadyinlist)
    {
        if(!(*albumiterator)->musicbrainzalbumid.compare(albumid))
            alreadyinlist=TRUE;
        albumiterator++;
    }
    return alreadyinlist;
}

bool musicbrainzconnect::findsong(mediatag *Song)
{
    bool success=FALSE;
    //Check what is already given, and decide wich query to use with this
    //Case one: Only the trackname is given, and since we know how long the song is, we still stay a chance
    if(!Song->title.isEmpty()&&Song->album.isEmpty()&&Song->artist.isEmpty()&&Song->number==0&&Song->year==0)
        success=TitleOnly(Song);
    //second case: Trackname, number and of cause the length are known, rest is missing
    else if(!Song->title.isEmpty()&&Song->album.isEmpty()&&Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
        success=TitleNumber(Song);
    //Third case: Trackname, number,and artist are known, rest is missing
    else if(!Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->album.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=TitleNumberArtist(Song,retry);
            retry++;
        }
    }
    else if(!Song->album.isEmpty()&&Song->title.isEmpty()&&Song->artist.isEmpty()&&Song->number==0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=AlbumOnly(Song,retry);
            retry++;
        }
    }
    //Fifth case:Artist and albumname are known, and the songlegth of cause
    else if(!Song->album.isEmpty()&&!Song->artist.isEmpty()&&Song->title.isEmpty()&&Song->number==0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=ArtistAlbum(Song,retry);
            retry++;
        }
    }
    //Sixth case:Albumname, Tracknumber and of cause songlength is given
    else if(!Song->album.isEmpty()&&Song->title.isEmpty()&&Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=NumberAlbum(Song,retry);
            retry++;
        }
    }
    //Seventh case:Only artistname,Tracknumber and of cause songlength is given
    else if(Song->album.isEmpty()&&Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=NumberArtist(Song,retry);
            retry++;
        }
    }
    //Eigth case:Artistname,Albumname and Tracknumber is given
    else if(!Song->album.isEmpty()&&Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=NumberArtistAlbum(Song,retry);
            retry++;
        }
    }
    //Nineth case:Only the Releasedate is missing
    else if(!Song->album.isEmpty()&&!Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=Releasdatemissing(Song,retry);
            retry++;
        }
    }
    //tenth case:Title and Albumname, and of cause songlength is given
    else if(!Song->album.isEmpty()&&!Song->title.isEmpty()&&Song->artist.isEmpty()&&Song->number==0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=TitleAlbum(Song,retry);
            retry++;
        }
    }
    //eleventh case:Title and Artistname, and of cause songlength is given
    else if(Song->album.isEmpty()&&!Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->number==0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=TitleArtist(Song,retry);
            retry++;
        }
    }
    //twelveth case:Title Album and Artistname is given
    else if(!Song->album.isEmpty()&&!Song->title.isEmpty()&&!Song->artist.isEmpty()&&Song->number==0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=TitleArtistAlbum(Song,retry);
            retry++;
        }
    }
    //thirteenth case:Title, Album, Artist and of cause tracklength is given
    else if(!Song->album.isEmpty()&&!Song->title.isEmpty()&&Song->artist.isEmpty()&&Song->number!=0&&Song->year==0)
    {
        //Since we need to load complete albums here, we first check for already fetched albums, so we set a retrycounter
        int retry=0;
        while (!success&&retry<2)
        {
            success=TitleNumberAlbum(Song,retry);
            retry++;
        }
    }
    return success;
}

/********************************************************************
 *Below are all parsers for the queries we have to musicbrainz      *
 *They parse the informations out of the xml-result from musicbrainz*
 ********************************************************************/

/*parse the artists out of the structure from xml-tree
 *<metadata><artist-list><artist>artistdata</artist></artist-list></metadata>
 *If the structure is other way, there is no result*/
QPtrList<musicbrainzartist> musicbrainzconnect::parseartists(QByteArray receiveddata)
{
    QPtrList<musicbrainzartist> parsedartists;
    //parse all artists out of the xml-tree
    QDomDocument *artistresult=new QDomDocument();
    artistresult->setContent(receiveddata);
    QDomElement metastart=artistresult->documentElement();
    if(!(metastart.tagName()!="metadata"))
    {
        QDomNode metatag=metastart.firstChild();
        QDomElement artistlist=metatag.toElement();
        if (artistlist.tagName()=="artist-list")
        {
            while(!metatag.isNull())
            {
                //Pull out all artiststuff,of the artist-list
                QDomNode artistlisttag=metatag.firstChild();
                while(!artistlisttag.isNull())
                {
                    QDomElement artist=artistlisttag.toElement();
                    if (artist.tagName()=="artist")
                    {
                        //get all stuff stated under artist-tag
                        musicbrainzartist *currartist=new musicbrainzartist;
                        currartist->artistid=artist.attribute("id","");
                        QDomNode artisttag=artistlisttag.firstChild();
                        while(!artisttag.isNull() )
                        {
                            QDomElement e=artisttag.toElement();
                            if(e.tagName()=="name")
                                currartist->artistname=e.text();
                            artisttag=artisttag.nextSibling();
                        }
                        parsedartists.append(currartist);
                    }
                    artistlisttag=artistlisttag.nextSibling();
                }
                metatag=metatag.nextSibling();
            }
        }
    }
    else
    {
        //something went wrong with the queryl, think about actions

    }
    delete artistresult;
    return parsedartists;
}

/*parse the albums out of the structure from xml-tree
 *<metadata><artist>artistdata<release-list><release>releasedata</release></releaselist></artist></metadata>
 *If the structure is other way, there is no result*/
QPtrList<musicbrainzalbum> musicbrainzconnect::parsealbumsfromartist(QByteArray receiveddata)
{
    QString artistname;
    QString artistid;
    QPtrList<musicbrainzalbum> parsedalbums;
    QDomDocument *albumresult=new QDomDocument();
    albumresult->setContent(receiveddata);
    QDomElement metastart=albumresult->documentElement();
    if(!(metastart.tagName()!="metadata"))
    {
        QDomNode metatag=metastart.firstChild();
        QDomElement meta=metatag.toElement();
        if (meta.tagName()=="artist")
        {
            artistid=meta.attribute("id","");
            QDomNode artisttag=metatag.firstChild();
            while(!artisttag.isNull())
            {
                QDomElement artist=artisttag.toElement();
                if (artist.tagName()=="name")
                    artistname=artist.text();
                if (artist.tagName()=="release-list")
                {
                    QDomNode releaselisttag=artisttag.firstChild();
                    while(!releaselisttag.isNull())
                    {
                        QDomElement releaselist=releaselisttag.toElement();
                        musicbrainzalbum *curralbum=new musicbrainzalbum;
                        curralbum->musicbrainzalbumid=releaselist.attribute("id","");
                        curralbum->artistname=artistname;
                        curralbum->musicbrainzartistid=artistid;
                        //Pull out all albums from releaselist
                        QDomNode releasetag=releaselisttag.firstChild();
                        while(!releasetag.isNull())
                        {
                            QDomElement release=releasetag.toElement();
                            if (release.tagName()=="title")
                            {
                                curralbum->albumname=release.text();
                                parsedalbums.append(curralbum);
                            }
                            if (release.tagName()=="release-event-list")
                            {
                                QDomNode eventtag=releasetag.firstChild();
                                while(!eventtag.isNull())
                                {
                                    QDomElement event=eventtag.toElement();
                                    if (event.tagName()=="event")
                                    {
                                        QString data=event.attribute("date","");
                                        data=data.left(4);
                                        bool ok;
                                        curralbum->releasedate=data.toInt(&ok,10);
                                    }
                                    eventtag=eventtag.nextSibling();
                                }
                            }
                            releasetag=releasetag.nextSibling();
                        }
                        releaselisttag=releaselisttag.nextSibling();
                    }
                }
                artisttag=artisttag.nextSibling();
            }
        }
    }
    else
    {
        //something went wrong with the queryl, think about actions

    }
    delete albumresult;
    return parsedalbums;
}

/*parse all tracks out of the structure from xml-tree
 *<metadata><release>releasedata<track-list><track>trackdata</track></track-list></release></metadata>
 *If the structure is other way, there is no result*/
int musicbrainzconnect::parsetracksfromalbum(QByteArray receiveddata,musicbrainzalbum *curralbum)
{
    int numtracks=0;
    QString artistid=curralbum->musicbrainzalbumid;
    QDomDocument *trackresult=new QDomDocument();
    trackresult->setContent(receiveddata);
    QDomElement metastart=trackresult->documentElement();
    if(!(metastart.tagName()!="metadata"))
    {
        QDomNode metatag=metastart.firstChild();
        QDomElement meta=metatag.toElement();
        if (meta.tagName()=="release"&&meta.attribute("id","")==artistid)
        {
            QDomNode releasetag=metatag.firstChild();
            while(!releasetag.isNull())
            {
                QDomElement release=releasetag.toElement();
                if (release.tagName()=="track-list")
                {
                    QDomNode tracklisttag=releasetag.firstChild();
                    while(!tracklisttag.isNull())
                    {
                        //Pull out all tracks from trackslist
                        QDomElement tracklist=tracklisttag.toElement();
                        musicbrainztrack *currtrack=new musicbrainztrack;
                        numtracks++;
                        currtrack->tracknumber=numtracks;
                        currtrack->musicbrainztrackid=tracklist.attribute("id","");
                        QDomNode tracktag=tracklisttag.firstChild();
                        while(!tracktag.isNull())
                        {
                            QDomElement track=tracktag.toElement();
                            if (track.tagName()=="title")
                            {
                                currtrack->trackname=track.text();
                            }
                            if (track.tagName()=="duration")
                            {
                                int duration=0;
                                bool ok;
                                duration=track.text().toLong(&ok,10);
                                currtrack->duration=duration;
                            }
                            tracktag=tracktag.nextSibling();
                        }
                        curralbum->tracklist.append(currtrack);
                        tracklisttag=tracklisttag.nextSibling();
                    }
                }
                releasetag=releasetag.nextSibling();
            }
        }
    }
    else
    {
        //something went wrong with the query, think about actions

    }
    delete trackresult;
    return numtracks;
}

/*Parse out albums containing the searched song
 *<metadata><track-list><track>trackdata<artist>artistdata</artist>
 *<release-list><release>releasedata</release></release-list></track></metadata>
 *If the structure is other way, there is no result*/
QPtrList<musicbrainzalbum> musicbrainzconnect::parsetracks(QByteArray receiveddata)
{
    QPtrList<musicbrainzalbum> parsedalbums;
    QDomDocument *trackresult=new QDomDocument();
    trackresult->setContent(receiveddata);
    QDomElement metastart=trackresult->documentElement();
    if(!(metastart.tagName()!="metadata"))
    {
        QDomNode metatag=metastart.firstChild();
        QDomElement meta=metatag.toElement();
        if (meta.tagName()=="track-list")
        {
            QDomNode tracklisttag=metatag.firstChild();
            while(!tracklisttag.isNull())
            {
                QDomElement tracklist=tracklisttag.toElement();
                if (tracklist.tagName()=="track")
                {
                    musicbrainzalbum *curralbum=new musicbrainzalbum;
                    curralbum->tracklist.setAutoDelete(TRUE);
                    musicbrainztrack *currtrack=new musicbrainztrack;
                    currtrack->musicbrainztrackid=tracklist.attribute("id","");
                    QDomNode tracktag=tracklisttag.firstChild();
                    while(!tracktag.isNull())
                    {
                        QDomElement track=tracktag.toElement();
                        if (track.tagName()=="title")
                            currtrack->trackname=track.text();
                        if (track.tagName()=="duration")
                        {
                            int duration=0;
                            bool ok;
                            duration=track.text().toLong(&ok,10);
                            currtrack->duration=duration;
                        }
                        if (track.tagName()=="artist")
                        {
                            curralbum->musicbrainzartistid=track.attribute("id","");
                            QDomNode artisttag=tracktag.firstChild();
                            while(!artisttag.isNull())
                            {
                                QDomElement artist=artisttag.toElement();
                                if(artist.tagName()=="name")
                                    curralbum->artistname=artist.text();
                                artisttag=artisttag.nextSibling();
                            }
                        }
                        if (track.tagName()="release-list")
                        {
                            QDomNode releaselisttag=tracktag.firstChild();
                            while(!releaselisttag.isNull())
                            {
                                QDomElement releaselist=releaselisttag.toElement();
                                if(releaselist.tagName()=="release")
                                {
                                    curralbum->musicbrainzalbumid=releaselist.attribute("id","");
                                    QDomNode releasetag=releaselisttag.firstChild();
                                    while(!releasetag.isNull())
                                    {
                                        QDomElement release=releasetag.toElement();
                                        if(release.tagName()=="title")
                                            curralbum->albumname=release.text();
                                        if(release.tagName()=="track-list")
                                        {
                                            bool ok;
                                            currtrack->tracknumber=1+release.attribute("offset","").toLong(&ok,10);
                                        }
                                        releasetag=releasetag.nextSibling();
                                    }
                                }
                                releaselisttag=releaselisttag.nextSibling();
                            }
                        }
                        tracktag=tracktag.nextSibling();
                    }
                    curralbum->tracklist.append(currtrack);
                    parsedalbums.append(curralbum);
                }
                tracklisttag=tracklisttag.nextSibling();
            }
        }
    }
    else
    {
        //something went wrong with the query, think about actions

    }

    delete trackresult;
    return parsedalbums;
}

/*Parse out albums matching given name
 *<metadata><release-list><release><artist>artistname</artist></release></release-list></metadata>
 *If the structure is other way, there is no result*/
QPtrList<musicbrainzalbum> musicbrainzconnect::parsealbums(QByteArray receiveddata)
{
    QPtrList<musicbrainzalbum> parsedalbums;
    QDomDocument *albumresult=new QDomDocument();
    albumresult->setContent(receiveddata);
    QDomElement metastart=albumresult->documentElement();
    if(!(metastart.tagName()!="metadata"))
    {
        QDomNode metatag=metastart.firstChild();
        QDomElement meta=metatag.toElement();
        if (meta.tagName()=="release-list")
        {
            QDomNode releaselisttag=metatag.firstChild();
            while(!releaselisttag.isNull())
            {
                QDomElement releaselist=releaselisttag.toElement();
                if (releaselist.tagName()=="release")
                {
                    QDomElement releaselist=releaselisttag.toElement();
                    musicbrainzalbum *curralbum=new musicbrainzalbum;
                    curralbum->musicbrainzalbumid=releaselist.attribute("id","");
                    QDomNode releasetag=releaselisttag.firstChild();
                    while(!releasetag.isNull())
                    {
                        QDomElement release=releasetag.toElement();
                        if (release.tagName()=="title")
                            curralbum->albumname=release.text();
                        if (release.tagName()=="artist")
                        {
                            curralbum->musicbrainzartistid=release.attribute("id","");
                            QDomNode artisttag=releasetag.firstChild();
                            while(!artisttag.isNull())
                            {
                                QDomElement artist=artisttag.toElement();
                                if (artist.tagName()=="name")
                                    curralbum->artistname=artist.text();
                                artisttag=artisttag.nextSibling();
                            }
                        }
                        if (release.tagName()=="release-event-list")
                        {
                            QDomNode eventtag=releasetag.firstChild();
                            while(!eventtag.isNull())
                            {
                                QDomElement event=eventtag.toElement();
                                if (event.tagName()=="event")
                                {
                                    QString data=event.attribute("date","");
                                    data=data.left(4);
                                    bool ok;
                                    curralbum->releasedate=data.toInt(&ok,10);
                                }
                                eventtag=eventtag.nextSibling();
                            }
                        }
                        releasetag=releasetag.nextSibling();
                    }
                    parsedalbums.append(curralbum);
                }
                releaselisttag=releaselisttag.nextSibling();
            }
        }
    }
    else
    {
        //something went wrong with the query, think about actions


    }
    delete albumresult;
    return parsedalbums;
}

/*********************************************************************************************************************
 *Here follow the specialized findfuntions for the given input                                                       *
 *They are put out of the findfile-funtion, to get a clearer structure, and the program is easier to understand      *
 *I know that this can be done with much less code, but this way, you always know what is the reason for misbehaviour*
 *And I can optimise the single queries for speed sometime
 *********************************************************************************************************************/

//Find match, when only the tracktitle is given, with help of the tracklength
bool musicbrainzconnect::TitleOnly(mediatag *Song)
{
    bool success=FALSE;
    QString trackname=Song->title;
    trackname.replace(' ','+');
    QString query=QString("/ws/1/track/?type=xml&title=%1&").arg(trackname);
    QByteArray receiveddata=musicbrainzquery(query);
    if (!receiveddata.isEmpty())
    {
        QPtrList<musicbrainzalbum> albumlist=parsetracks(receiveddata);
        albumlist.setAutoDelete(TRUE);
        QPtrList<musicbrainzalbum>::Iterator index=albumlist.begin();
        bool found=FALSE;
        while(index!=albumlist.end()&&!found)
        {
            QPtrList<musicbrainztrack>::Iterator index2=(*index)->tracklist.begin();
            while (index2!=(*index)->tracklist.end()&&!found)
            {
                //compare all found tracks with our songlength(+-2seconds), and jump out if we have a match
                if ((*index2)->duration>=((Song->songlength-2)*1000)&&(*index2)->duration<=((Song->songlength+2)*1000))
                {
                    found=TRUE;
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*index2)->trackname;
                    Song->number=(*index2)->tracknumber;
                    Song->artist=(*index)->artistname;
                    Song->album=(*index)->albumname;
                    //since we don't know the releasdate yet, we have to fetch it first
                    query=QString("/ws/1/release/%1?type=xml&inc=release-events").arg((*index)->musicbrainzalbumid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        //Just catch out the releasdate
                        QString data=QString(receiveddata);
                        int position=data.find("event date=");
                        data=data.remove(0,position+12);
                        data=data.left(4);
                        bool ok;
                        Song->year=data.toInt(&ok,10);
                    }
                }
                index2++;
            }
            index++;
        }
    }
    return success;
}

//Find match, when tracktitle and tracknumber are given, with help of tracklength
bool musicbrainzconnect::TitleNumber(mediatag *Song)
{
    bool success=FALSE;
    QString trackname=Song->title;
    trackname.replace(' ','+');
    QString query=QString("/ws/1/track/?type=xml&title=%1&").arg(trackname);
    QByteArray receiveddata=musicbrainzquery(query);
    if (!receiveddata.isEmpty())
    {
        QPtrList<musicbrainzalbum> albumlist=parsetracks(receiveddata);
        albumlist.setAutoDelete(TRUE);
        QPtrList<musicbrainzalbum>::Iterator index=albumlist.begin();
        bool found=FALSE;
        while(index!=albumlist.end()&&!found)
        {
            QPtrList<musicbrainztrack>::Iterator index2=(*index)->tracklist.begin();
            while (index2!=(*index)->tracklist.end()&&!found)
            {
                //First check if we match with the tracknumber
                if ((*index2)->tracknumber==Song->number)
                {
                    //compare all found tracks with our songlength(+-2seconds), and jump out if we have a match
                    if ((*index2)->duration>=((Song->songlength-3)*1000)&&(*index2)->duration<=((Song->songlength+3)*1000))
                    {
                        found=TRUE;
                        success=true;
                        //set all values of the mediatag, to the parameters found in our match
                        Song->title=(*index2)->trackname;
                        Song->number=(*index2)->tracknumber;
                        Song->artist=(*index)->artistname;
                        Song->album=(*index)->albumname;
                        //since we don't know the releasdate yet, we have to fetch it first
                        query=QString("/ws/1/release/%1?type=xml&inc=release-events").arg((*index)->musicbrainzalbumid);
                        receiveddata=musicbrainzquery(query);
                        if (!receiveddata.isEmpty())
                        {
                            //Just catch out the releasdate
                            QString data=QString(receiveddata);
                            int position=data.find("event date=");
                            data=data.remove(0,position+12);
                            data=data.left(4);
                            bool ok;
                            Song->year=data.toInt(&ok,10);
                        }
                    }
                }
                index2++;
            }
            index++;
        }
    }
    return success;
}

bool musicbrainzconnect::TitleNumberArtist(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                            receiveddata=musicbrainzquery(query);
                            if (!receiveddata.isEmpty())
                            {
                                parsetracksfromalbum(receiveddata,(*albumiterator));
                                if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                {
                                    //We have to make a copy of the original, because it is deleted, when this function returns
                                    musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                    (*albumiterator)->copy(albumcopy);
                                    fetchedalbums->append(albumcopy);
                                    if (settingsfile.databasetype)
                                        database->writealbum(albumcopy);
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            QString trackcompare=QString((*trackiterator)->trackname);
            trackcompare=trackcompare.lower().remove("'").remove("/").remove(" ");
            if (!(trackcompare.compare(Song->title.lower().remove("'").remove("/").remove(" ")))&&(*trackiterator)->tracknumber==Song->number)
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::AlbumOnly(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //Fetch albums from musicbrainz, cause we don't have it in list
        actualalbums.setAutoDelete(TRUE);
        QString albumname=Song->album;
        albumname.replace(' ','+');
        QString query=QString("/ws/1/release/?type=xml&title=%1").arg(albumname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            actualalbums=parsealbums(receiveddata);
            //Fetch all songs of valid albums and enter them in already fetchedalbums
            QPtrList<musicbrainzalbum>::Iterator searchindex=actualalbums.begin();
            while (searchindex!=actualalbums.end())
            {
                if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
                {
                    query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg(QString((*searchindex)->musicbrainzalbumid));
                    QByteArray receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        int songcount=parsetracksfromalbum(receiveddata,((*searchindex)));
                        if (!songcount)
                            cerr<<"No songs in album"<<endl;
                        else
                        {
                            //Check for doubles, before entry
                            if (!checkdouble((*searchindex)->musicbrainzalbumid))
                            {
                                //We have to make a copy of the original, because it is deleted, when this function returns
                                musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                (*searchindex)->copy(albumcopy);
                                fetchedalbums->append(albumcopy);
                                if (settingsfile.databasetype)
                                    database->writealbum(albumcopy);
                            }
                        }
                    }
                }
                searchindex++;
            }
        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
            {
                success=TRUE;
                //set all values of the mediatag, to the parameters found in our match
                Song->title=(*trackiterator)->trackname;
                Song->number=(*trackiterator)->tracknumber;
                Song->artist=(*albumiterator)->artistname;
                Song->album=(*albumiterator)->albumname;
                Song->year=(*albumiterator)->releasedate;
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::ArtistAlbum(mediatag *Song, int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" ")))&&!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //We fetch the artistlist first, so we get the best matches
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums, but only fetch relevant ones
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            if(!(Song->album.lower().remove("'").remove(" ").remove("/").compare((*albumiterator)->albumname.lower().remove("'").remove(" ").remove("/"))))
                            {
                                query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                                receiveddata=musicbrainzquery(query);
                                if (!receiveddata.isEmpty())
                                {
                                    parsetracksfromalbum(receiveddata,(*albumiterator));
                                    if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                    {
                                        //We have to make a copy of the original, because it is deleted, when this function returns
                                        musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                        (*albumiterator)->copy(albumcopy);
                                        fetchedalbums->append(albumcopy);
                                        if (settingsfile.databasetype)
                                            database->writealbum(albumcopy);
                                    }
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        if ((*albumiterator)->tracklist.count())
        {
            QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
            while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
                trackiterator++;
            }
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::NumberAlbum(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //Fetch albums from musicbrainz, cause we don't have it in list
        actualalbums.setAutoDelete(TRUE);
        QString albumname=Song->album;
        albumname.replace(' ','+');
        QString query=QString("/ws/1/release/?type=xml&title=%1").arg(albumname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            actualalbums=parsealbums(receiveddata);
            //Fetch all songs of valid albums and enter them in already fetchedalbums
            QPtrList<musicbrainzalbum>::Iterator searchindex=actualalbums.begin();
            while (searchindex!=actualalbums.end())
            {
                if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
                {
                    query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg(QString((*searchindex)->musicbrainzalbumid));
                    QByteArray receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        int songcount=parsetracksfromalbum(receiveddata,((*searchindex)));
                        if (!songcount)
                            cerr<<"No songs in album"<<endl;
                        else
                        {
                            //Check for doubles, before entry
                            if (!checkdouble((*searchindex)->musicbrainzalbumid))
                            {
                                //We have to make a copy of the original, because it is deleted, when this function returns
                                musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                (*searchindex)->copy(albumcopy);
                                fetchedalbums->append(albumcopy);
                                if (settingsfile.databasetype)
                                    database->writealbum(albumcopy);
                            }
                        }
                    }
                }
                searchindex++;
            }
        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            if ((*trackiterator)->tracknumber==Song->number)
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::NumberArtist(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                            receiveddata=musicbrainzquery(query);
                            if (!receiveddata.isEmpty())
                            {
                                parsetracksfromalbum(receiveddata,(*albumiterator));
                                if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                {
                                    //We have to make a copy of the original, because it is deleted, when this function returns
                                    musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                    (*albumiterator)->copy(albumcopy);
                                    fetchedalbums->append(albumcopy);
                                    if (settingsfile.databasetype)
                                        database->writealbum(albumcopy);
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            if ((*trackiterator)->tracknumber==Song->number)
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::NumberArtistAlbum(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" ")))&&!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //We fetch the artistlist first, so we get the best matches
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums, but only fetch relevant ones
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            if(!(Song->album.lower().remove("'").remove(" ").remove("/").compare((*albumiterator)->albumname.lower().remove("'").remove(" ").remove("/"))))
                            {
                                query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                                receiveddata=musicbrainzquery(query);
                                if (!receiveddata.isEmpty())
                                {
                                    parsetracksfromalbum(receiveddata,(*albumiterator));
                                    if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                    {
                                        //We have to make a copy of the original, because it is deleted, when this function returns
                                        musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                        (*albumiterator)->copy(albumcopy);
                                        fetchedalbums->append(albumcopy);
                                        if (settingsfile.databasetype)
                                            database->writealbum(albumcopy);
                                    }
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        if ((*albumiterator)->tracklist.count())
        {
            QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
            while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
            {
                if ((*trackiterator)->tracknumber==Song->number)
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
                trackiterator++;
            }
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::TitleAlbum(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //Fetch albums from musicbrainz, cause we don't have it in list
        actualalbums.setAutoDelete(TRUE);
        QString albumname=Song->album;
        albumname.replace(' ','+');
        QString query=QString("/ws/1/release/?type=xml&title=%1").arg(albumname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            actualalbums=parsealbums(receiveddata);
            //Fetch all songs of valid albums and enter them in already fetchedalbums
            QPtrList<musicbrainzalbum>::Iterator searchindex=actualalbums.begin();
            while (searchindex!=actualalbums.end())
            {
                if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
                {
                    query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg(QString((*searchindex)->musicbrainzalbumid));
                    QByteArray receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        int songcount=parsetracksfromalbum(receiveddata,((*searchindex)));
                        if (!songcount)
                            cerr<<"No songs in album"<<endl;
                        else
                        {
                            //Check for doubles, before entry
                            if (!checkdouble((*searchindex)->musicbrainzalbumid))
                            {
                                //We have to make a copy of the original, because it is deleted, when this function returns
                                musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                (*searchindex)->copy(albumcopy);
                                fetchedalbums->append(albumcopy);
                                if (settingsfile.databasetype)
                                    database->writealbum(albumcopy);
                            }
                        }
                    }
                }
                searchindex++;
            }
        }
    }
    //We have a albumlist now, so we can search for the right trackname in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            QString trackcompare=QString((*trackiterator)->trackname);
            trackcompare=trackcompare.lower().remove("'").remove("/").remove(" ");
            if (!(trackcompare.compare(Song->title.lower().remove("'").remove("/").remove(" "))))
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::TitleArtist(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                            receiveddata=musicbrainzquery(query);
                            if (!receiveddata.isEmpty())
                            {
                                parsetracksfromalbum(receiveddata,(*albumiterator));
                                if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                {
                                    //We have to make a copy of the original, because it is deleted, when this function returns
                                    musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                    (*albumiterator)->copy(albumcopy);
                                    fetchedalbums->append(albumcopy);
                                    if (settingsfile.databasetype)
                                        database->writealbum(albumcopy);
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            QString trackcompare=QString((*trackiterator)->trackname);
            trackcompare=trackcompare.lower().remove("'").remove("/").remove(" ");
            if (!(trackcompare.compare(Song->title.lower().remove("'").remove("/").remove(" "))))
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::Releasdatemissing(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" ")))&&!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //We fetch the artistlist first, so we get the best matches
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist
                query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                receiveddata=musicbrainzquery(query);
                if (!receiveddata.isEmpty())
                {
                    actualalbums=parsealbumsfromartist(receiveddata);
                    //Ask musicbrainz for the tracktitles of the given albums, but only fetch relevant ones
                    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                    while (albumiterator!=actualalbums.end())
                    {
                        if(!(Song->album.lower().remove("'").remove(" ").remove("/").compare((*albumiterator)->albumname.lower().remove("'").remove(" ").remove("/"))))
                        {
                            query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                            receiveddata=musicbrainzquery(query);
                            if (!receiveddata.isEmpty())
                            {
                                parsetracksfromalbum(receiveddata,(*albumiterator));
                                if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                {
                                    //We have to make a copy of the original, because it is deleted, when this function returns
                                    musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                    (*albumiterator)->copy(albumcopy);
                                    fetchedalbums->append(albumcopy);
                                    if (settingsfile.databasetype)
                                        database->writealbum(albumcopy);
                                }
                            }
                        }
                        albumiterator++;
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right tracklength in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        if ((*albumiterator)->tracklist.count())
        {
            QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
            while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
            {
                if ((*trackiterator)->tracknumber==Song->number)
                {
                    if (!(Song->title.lower().remove("'").remove(" ").remove("/")).compare((*trackiterator)->trackname.lower().remove("'").remove(" ").remove("/")))
                    {
                        success=TRUE;
                        //set all values of the mediatag, to the parameters found in our match
                        Song->title=(*trackiterator)->trackname;
                        Song->number=(*trackiterator)->tracknumber;
                        Song->artist=(*albumiterator)->artistname;
                        Song->album=(*albumiterator)->albumname;
                        Song->year=(*albumiterator)->releasedate;
                    }
                }
                trackiterator++;
            }
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::TitleArtistAlbum(mediatag *Song, int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" ")))&&!(((*searchindex)->artistname.lower().remove("'").remove("/").remove(" ")).compare(Song->artist.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //We fetch the artistlist first, so we get the best matches
        actualalbums.setAutoDelete(TRUE);
        QString artistname=Song->artist;
        artistname.replace(' ','+');
        QString query=QString("/ws/1/artist/?type=xml&name=%1").arg(artistname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            QPtrList<musicbrainzartist> artistlist=parseartists(receiveddata);
            artistlist.setAutoDelete(TRUE);
            //Fetch out all entries with the right artist
            QPtrList<musicbrainzartist>::Iterator artistiterator=artistlist.begin();
            while(artistiterator!=artistlist.end())
            {
                //Fetch all the albums of the given artist,if the artist matches really
                if(!(Song->artist.lower().remove("'").remove(" ").remove("/").compare((*artistiterator)->artistname.lower().remove("'").remove(" ").remove("/"))))
                {
                    query=QString("/ws/1/artist/%1?type=xml&inc=sa-Official+release-events").arg((*artistiterator)->artistid);
                    receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        actualalbums=parsealbumsfromartist(receiveddata);
                        //Ask musicbrainz for the tracktitles of the given albums, but only fetch relevant ones
                        QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
                        while (albumiterator!=actualalbums.end())
                        {
                            if(!(Song->album.lower().remove("'").remove(" ").remove("/").compare((*albumiterator)->albumname.lower().remove("'").remove(" ").remove("/"))))
                            {
                                query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg((*albumiterator)->musicbrainzalbumid);
                                receiveddata=musicbrainzquery(query);
                                if (!receiveddata.isEmpty())
                                {
                                    parsetracksfromalbum(receiveddata,(*albumiterator));
                                    if (!checkdouble((*albumiterator)->musicbrainzalbumid))
                                    {
                                        //We have to make a copy of the original, because it is deleted, when this function returns
                                        musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                        (*albumiterator)->copy(albumcopy);
                                        fetchedalbums->append(albumcopy);
                                        if (settingsfile.databasetype)
                                            database->writealbum(albumcopy);
                                    }
                                }
                            }
                            albumiterator++;
                        }
                    }
                }
                artistiterator++;
            }

        }
    }
    //We have a albumlist now, so we can search for the right title in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        if ((*albumiterator)->tracklist.count())
        {
            QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
            while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
            {
                QString trackcompare=QString((*trackiterator)->trackname);
                trackcompare=trackcompare.lower().remove("'").remove("/").remove(" ");
                if (!(trackcompare.compare(Song->title.lower().remove("'").remove("/").remove(" "))))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
                trackiterator++;
            }
        }
        albumiterator++;
    }
    return success;
}

bool musicbrainzconnect::TitleNumberAlbum(mediatag *Song,int retry)
{
    bool success=FALSE;
    QPtrList<musicbrainzalbum> actualalbums;
    if (!retry)
    {
        actualalbums.setAutoDelete(FALSE);//Important,otherwise we loose our albums,on second readout
        //Check out the already fetched albumslist on the first go
        QPtrList<musicbrainzalbum>::Iterator searchindex=fetchedalbums->begin();
        while (searchindex!=fetchedalbums->end())
        {
            //Throw all albummatches on the actualalbumslist
            if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
            {
                actualalbums.append((*searchindex));
            }
            searchindex++;
        }
    }
    else
    {
        //Fetch albums from musicbrainz, cause we don't have it in list
        actualalbums.setAutoDelete(TRUE);
        QString albumname=Song->album;
        albumname.replace(' ','+');
        QString query=QString("/ws/1/release/?type=xml&title=%1").arg(albumname);
        QByteArray receiveddata=musicbrainzquery(query);
        if (!receiveddata.isEmpty())
        {
            actualalbums=parsealbums(receiveddata);
            //Fetch all songs of valid albums and enter them in already fetchedalbums
            QPtrList<musicbrainzalbum>::Iterator searchindex=actualalbums.begin();
            while (searchindex!=actualalbums.end())
            {
                if (!(((*searchindex)->albumname.lower().remove("'").remove("/").remove(" ")).compare(Song->album.lower().remove("'").remove("/").remove(" "))))
                {
                    query=QString("/ws/1/release/%1?type=xml&inc=tracks").arg(QString((*searchindex)->musicbrainzalbumid));
                    QByteArray receiveddata=musicbrainzquery(query);
                    if (!receiveddata.isEmpty())
                    {
                        int songcount=parsetracksfromalbum(receiveddata,((*searchindex)));
                        if (!songcount)
                            cerr<<"No songs in album"<<endl;
                        else
                        {
                            //Check for doubles, before entry
                            if (!checkdouble((*searchindex)->musicbrainzalbumid))
                            {
                                //We have to make a copy of the original, because it is deleted, when this function returns
                                musicbrainzalbum *albumcopy=new musicbrainzalbum();
                                (*searchindex)->copy(albumcopy);
                                fetchedalbums->append(albumcopy);
                                if (settingsfile.databasetype)
                                    database->writealbum(albumcopy);
                            }
                        }
                    }
                }
                searchindex++;
            }
        }
    }
    //We have a albumlist now, so we can search for the right trackname in it
    QPtrList<musicbrainzalbum>::Iterator albumiterator=actualalbums.begin();
    while(albumiterator!=actualalbums.end()&&!success)
    {
        QPtrList<musicbrainztrack>::Iterator trackiterator=(*albumiterator)->tracklist.begin();
        while(trackiterator!=(*albumiterator)->tracklist.end()&&!success)
        {
            QString trackcompare=QString((*trackiterator)->trackname);
            trackcompare=trackcompare.lower().remove("'").remove("/").remove(" ");
            if (!(trackcompare.compare(Song->title.lower().remove("'").remove("/").remove(" ")))&&(*trackiterator)->tracknumber==Song->number)
            {
                if ((*trackiterator)->duration>=((Song->songlength-2)*1000)&&(*trackiterator)->duration<=((Song->songlength+2)*1000))
                {
                    success=TRUE;
                    //set all values of the mediatag, to the parameters found in our match
                    Song->title=(*trackiterator)->trackname;
                    Song->number=(*trackiterator)->tracknumber;
                    Song->artist=(*albumiterator)->artistname;
                    Song->album=(*albumiterator)->albumname;
                    Song->year=(*albumiterator)->releasedate;
                }
            }
            trackiterator++;
        }
        albumiterator++;
    }
    return success;
}

void musicbrainzconnect::getfinished(int id, bool error)
{
    queryOk=FALSE;
    if (transactionid==id)
    {
        if (!error)
        {
            queryOk=TRUE;
        }
        else
            cerr<<url->errorString()<<endl;
        notfinished=FALSE;
    }
}

musicbrainzalbum::musicbrainzalbum()
{
    releasedate=0;
    tracklist.setAutoDelete(TRUE);
}

musicbrainzalbum::~musicbrainzalbum()
{}

void musicbrainzalbum::copy(musicbrainzalbum *destination)
{
    //We have to make a real copy of albums we want to keep for runtime, cause copying pointers is not enough
    destination->albumname=this->albumname;
    destination->artistname=this->artistname;
    destination->musicbrainzalbumid=this->musicbrainzalbumid;
    destination->musicbrainzartistid=this->musicbrainzartistid;
    destination->releasedate=this->releasedate;
    QPtrList<musicbrainztrack>::Iterator trackiterator=this->tracklist.begin();
    while(trackiterator!=this->tracklist.end())
    {
        musicbrainztrack *currtrack=new musicbrainztrack;
        currtrack->trackname=(*trackiterator)->trackname;
        currtrack->tracknumber=(*trackiterator)->tracknumber;
        currtrack->musicbrainztrackid=(*trackiterator)->musicbrainztrackid;
        currtrack->duration=(*trackiterator)->duration;
        destination->tracklist.append(currtrack);
        trackiterator++;
    }
}
