Exemple #1
0
void
CoverFetchInfoPayload::prepareUrls()
{
    KUrl url;
    CoverFetch::Metadata metadata;

    switch( m_src )
    {
    default:
    case CoverFetch::LastFm:
        url.setScheme( "http" );
        url.setHost( "ws.audioscrobbler.com" );
        url.setPath( "/2.0/" );
        url.addQueryItem( "api_key", Amarok::lastfmApiKey() );
        url.addQueryItem( "album", sanitizeQuery( album()->name() ) );

        if( album()->hasAlbumArtist() )
        {
            url.addQueryItem( "artist", sanitizeQuery( album()->albumArtist()->name() ) );
        }
        url.addQueryItem( "method", method() );

        metadata[ "source" ] = "Last.fm";
        metadata[ "method" ] = method();
        break;
    }

    if( url.isValid() )
        m_urls.insert( url, metadata );
}
Exemple #2
0
void
CoverFetchArtPayload::prepareUrls()
{
    if( m_src == CoverFetch::Google )
    {
        // google is special
        prepareGoogleUrls();
        return;
    }

    QXmlStreamReader xml( m_xml );
    switch( m_src )
    {
    default:
    case CoverFetch::LastFm:
        prepareLastFmUrls( xml );
        break;
    case CoverFetch::Yahoo:
        prepareYahooUrls( xml );
        break;
    case CoverFetch::Discogs:
        prepareDiscogsUrls( xml );
        break;
    }

    if( xml.hasError() )
    {
        debug() << QString( "Error occured when pareparing %1 urls for %2: %3" )
            .arg( sourceString(), (album() ? album()->name() : "'unknown'"), xml.errorString() );
        debug() << urls();
    }
}
Exemple #3
0
void PlaylistItem::refAlbum()
{
    if( Amarok::entireAlbums() )
    {
        if( listView()->m_albums[artist_album()].find( album() ) == listView()->m_albums[artist_album()].end() )
            listView()->m_albums[artist_album()][album()] = new PlaylistAlbum;
        m_album = listView()->m_albums[artist_album()][album()];
        m_album->refcount++;
    }
}
Exemple #4
0
QNetworkReply* 
lastfm::Track::updateNowPlaying( int duration ) const
{
    QMap<QString, QString> map = params("updateNowPlaying");
    map["duration"] = QString::number( duration );
    if ( !album().isNull() ) map["album"] = album();
    map["context"] = extra("playerId");

    qDebug() << map;

    return ws::post(map);
}
void
TrackImageFetcher::startAlbum()
{
    if (!album().isNull())
    {
        QUrl imageUrl = url( "album" );

        if ( imageUrl.isValid() )
            connect( lastfm::nam()->get( QNetworkRequest( imageUrl ) ), SIGNAL(finished()), SLOT(onAlbumImageDownloaded()) );
        else
            connect( album().getInfo(), SIGNAL(finished()), SLOT(onAlbumGotInfo()) );
    }
    else
        startTrack();
}
void
AlbumTagsRequest::start()
{
    get( "http://ws.audioscrobbler.com/1.0/album/toptags.xml?"
         "artist=" + UnicornUtils::urlEncodeItem( artist() ) +
         "&album=" + UnicornUtils::urlEncodeItem( album() ) );
}
Exemple #7
0
Meta::AlbumPtr UpnpCache::getAlbum(const QString& name, const QString &artist )
{
    if( m_albumMap.contains( name, artist ) )
        return m_albumMap.value( name, artist );

    Meta::UpnpAlbumPtr album( new Meta::UpnpAlbum( name ) );
    album->setAlbumArtist( Meta::UpnpArtistPtr::staticCast( getArtist( artist ) ) );
    m_albumMap.insert( Meta::AlbumPtr::staticCast( album ) );
    return Meta::AlbumPtr::staticCast( album );
}
Exemple #8
0
void
CoverFetchArtPayload::prepareLastFmUrls( QXmlStreamReader &xml )
{
    QSet<QString> artistSet;
    if( method() == "album.getinfo" )
    {
        artistSet << normalize( ( album() && album()->albumArtist() )
                                ? album()->albumArtist()->name()
                                : i18n( "Unknown Artist" ) );
    }
    else if( method() == "album.search" )
    {
        if( !m_wild && album() )
        {
            const Meta::TrackList tracks = album()->tracks();
            QStringList artistNames( "Various Artists" );
            foreach( const Meta::TrackPtr &track, tracks )
                artistNames << ( track->artist() ? track->artist()->name()
                                                 : i18n( "Unknown Artist" ) );
            artistSet = normalize( artistNames ).toSet();
        }
    }
    else return;
Exemple #9
0
void PlaylistItem::derefAlbum()
{
    if( Amarok::entireAlbums() && m_album )
    {
        m_album->refcount--;
        if( !m_album->refcount )
        {
            if (!listView()->m_prevAlbums.removeRef( m_album ))
		warning() << "Unable to remove album reference from "
		          << "listView.m_prevAlbums" << endl;
            listView()->m_albums[artist_album()].remove( album() );
            if( listView()->m_albums[artist_album()].isEmpty() )
                listView()->m_albums.remove( artist_album() );
            delete m_album;
        }
    }
}
	MediaInfo LocalFileResolver::ResolveInfo (const QString& file)
	{
		const auto& modified = QFileInfo (file).lastModified ();
		{
			QReadLocker locker (&CacheLock_);
			if (Cache_.contains (file))
			{
				const auto& pair = Cache_ [file];
				if (pair.first == modified)
					return pair.second;
			}
		}

		QMutexLocker tlLocker (&TaglibMutex_);

		auto r = GetFileRef (file);
		auto tag = r.tag ();
		if (!tag)
			throw ResolveError (file, "failed to get file tags");

		auto audio = r.audioProperties ();

		auto ftl = [] (const TagLib::String& str) { return QString::fromUtf8 (str.toCString (true)); };
		auto genres = ftl (tag->genre ()).split ('/', QString::SkipEmptyParts);
		std::for_each (genres.begin (), genres.end (),
				[] (QString& genre) { genre = genre.trimmed (); });

		MediaInfo info
		{
			file,
			ftl (tag->artist ()),
			ftl (tag->album ()),
			ftl (tag->title ()),
			genres,
			audio ? audio->length () : 0,
			static_cast<qint32> (tag->year ()),
			static_cast<qint32> (tag->track ())
		};
		{
			QWriteLocker locker (&CacheLock_);
			if (Cache_.size () > 200)
				Cache_.clear ();
			Cache_ [file] = qMakePair (modified, info);
		}
		return info;
	}
Exemple #11
0
QString RDLogLine::resolveWildcards(QString pattern)
{
  pattern.replace("%n",QString().sprintf("%06u",cartNumber()));
  pattern.replace("%h",QString().sprintf("%d",effectiveLength()));
  pattern.replace("%g",groupName());
  pattern.replace("%t",title());
  pattern.replace("%a",artist());
  pattern.replace("%l",album());
  pattern.replace("%y",year().toString("yyyy"));
  pattern.replace("%b",label());
  pattern.replace("%c",client());
  pattern.replace("%e",agency());
  pattern.replace("%m",composer());
  pattern.replace("%p",publisher());
  pattern.replace("%u",userDefined());

  return pattern;
}
Exemple #12
0
void PlaylistModel::onQueryFinished()
{
    QSparqlResult *result = static_cast<QSparqlResult*>(sender());

    if (result->size() > 0) {
        result->next();
        QSparqlResultRow row(result->current());

        PlaylistTrack *track = m_tracks.at(result->property("trackIndex").toInt());

        track->title = row.value("title").toString();
        track->duration = row.value("duration").toLongLong();

        QVariant artist(row.value("artist"));
        if (artist.isValid()) {
            track->artist = artist.toString();
        } else {
            track->artist = tr("Unknown artist");
            track->unknownArtist = true;
        }

        QVariant album(row.value("album"));
        if (album.isValid()) {
            track->album = album.toString();
        } else {
            track->album = tr("Unknown album");
            track->unknownAlbum = true;
        }
    }

    m_loadedTracks++;

    if (m_loadedTracks == m_tracks.size()) {
        m_loaded = true;
        emit loadedChanged();

        beginResetModel();
        m_rowCount = m_tracks.size();
        endResetModel();

        qDeleteAll(m_queries);
        m_queries.clear();
    }
}
QVariant
ScrobblesModel::Scrobble::attribute( int index ) const
{
    switch( index )
    {
    case Artist:
        return artist();
    case Title:
        return title();
    case Album:
        return album();
    case TimeStamp:
        return timestamp();
    case Loved:
        return isLoved();
    default:
        return QVariant();
    }
}
Exemple #14
0
QString
MetaBundle::infoByColumn( int column, bool pretty ) const
{
    switch( column )
    {
        case PlaylistItem::Filename:  return filename();
        case PlaylistItem::Title:     return title();
        case PlaylistItem::Artist:    return artist();
        case PlaylistItem::Album:     return album();
        case PlaylistItem::Year:      return year();
        case PlaylistItem::Comment:   return comment();
        case PlaylistItem::Genre:     return genre();
        case PlaylistItem::Track:     return track();
        case PlaylistItem::Directory: return directory();
        case PlaylistItem::Length:    return pretty ? prettyLength() : QString::number( length() );
        case PlaylistItem::Bitrate:   return pretty ? prettyBitrate() : QString::number( bitrate() );
        case PlaylistItem::Type:      return type( pretty );
    }
    return QString::null;
}
void TestMetaManager::read()
{
    QString album("Album: " + _meta->album());
    QString artist("Artist: " + _meta->artist());
    QString artwork("Artwork: " + _meta->artwork());
    QString copyright("Copyright: " + _meta->copyright());
    QString description("Description: " + _meta->description());
    QString encoder("Encoder: " + _meta->encoder());
    QString genre("Genre: " + _meta->genre());
    QString id("ID: " + _meta->id());
    QString language("Language: " + _meta->language());
    QString number("Number: " + QString().number(_meta->number()));
    QString publisher("Publisher: " + _meta->publisher());
    QString rating("Rating: " + _meta->rating());
    QString setting("Setting: " + _meta->setting());
    QString title("Title: " + _meta->title());
    QString url("Url: " + _meta->url());
    QString year("Year: " + QString().number(_meta->year()));

    ui->labelMeta->setText(album + "\n" + artist + "\n" + artwork + "\n" + copyright + "\n" +
                           description + "\n" + encoder + "\n" + genre + "\n" + id + "\n" +
                           language + "\n" + number + "\n" + publisher + "\n" + rating + "\n" +
                           setting + "\n" + title + "\n" + url + "\n" + year + "\n");
}
Exemple #16
0
// virtual
void CdDecoder::commitMetadata(Metadata *mdata)
{
    QMutexLocker lock(&getCdioMutex());

    StCdioDevice cdio(m_devicename);
    if (!cdio)
        return;

    Cddb::Toc toc;
    GetToc(cdio, toc);

    unsigned secs;
    Cddb::discid_t discID = Cddb::Discid(secs, toc.data(), toc.size() - 1);

    Cddb::Album album(discID, mdata->Genre().toLower().toUtf8());
    if (!Cddb::Read(album, album.genre, discID))
        album.toc = toc;

    album.isCompilation = mdata->Compilation();
    if (!mdata->Compilation())
        album.artist = mdata->Artist();
    else if (mdata->CompilationArtist() != album.artist)
        album.artist = mdata->CompilationArtist();

    album.title = mdata->Album();
    album.year = mdata->Year();

    if (album.tracks.size() < m_tracknum)
        album.tracks.resize(m_tracknum);

    Cddb::Track& track = album.tracks[m_tracknum - 1];
    track.title = mdata->Title();
    track.artist = mdata->Artist();

    Cddb::Write(album);
}
Exemple #17
0
int QuickTrackInfo::albumYear() const
{
    return album().year();
}
Exemple #18
0
QString QuickTrackInfo::albumName() const
{
    return album().name();
}
Exemple #19
0
QString RDLogLine::xml(int line) const
{
  QString ret;
#ifndef WIN32
  ret+="  <logLine>\n";
  ret+="    "+RDXmlField("line",line);
  ret+="    "+RDXmlField("id",id());
  ret+="    "+RDXmlField("type",RDLogLine::typeText(type()));
  ret+="    "+RDXmlField("cartType",RDCart::typeText(cartType()));
  ret+="    "+RDXmlField("cartNumber",cartNumber());
  ret+="    "+RDXmlField("cutNumber",cutNumber());
  ret+="    "+RDXmlField("groupName",groupName());
  ret+="    "+RDXmlField("groupColor",groupColor().name());
  ret+="    "+RDXmlField("title",title());
  ret+="    "+RDXmlField("artist",artist());
  ret+="    "+RDXmlField("publisher",publisher());
  ret+="    "+RDXmlField("composer",composer());
  ret+="    "+RDXmlField("album",album());
  ret+="    "+RDXmlField("label",label());
  if(year().isValid()) {
    ret+="    "+RDXmlField("year",year().year());
  }
  else {
    ret+="    "+RDXmlField("year");
  }
  ret+="    "+RDXmlField("client",client());
  ret+="    "+RDXmlField("agency",agency());
  ret+="    "+RDXmlField("userDefined",userDefined());
  ret+="    "+RDXmlField("usageCode",usageCode());
  ret+="    "+RDXmlField("enforceLength",enforceLength());
  ret+="    "+RDXmlField("forcedLength",RDGetTimeLength(forcedLength(),true));
  ret+="    "+RDXmlField("evergreen",evergreen());
  ret+="    "+RDXmlField("source",RDLogLine::sourceText(source()));
  ret+="    "+RDXmlField("timeType",RDLogLine::timeTypeText(timeType()));
  if(startTime(RDLogLine::Logged).isValid()&&
     (!startTime(RDLogLine::Logged).isNull())) {
    ret+="    "+RDXmlField("startTime",startTime(RDLogLine::Logged).
			   toString("hh:mm:ss.zzz"));
  }
  else {
    ret+="    "+RDXmlField("startTime");
  }
  ret+="    "+RDXmlField("transitionType",RDLogLine::transText(transType()));
  ret+="    "+RDXmlField("cutQuantity",cutQuantity());
  ret+="    "+RDXmlField("lastCutPlayed",lastCutPlayed());
  ret+="    "+RDXmlField("markerComment",markerComment());
  ret+="    "+RDXmlField("markerLabel",markerLabel());

  ret+="    "+RDXmlField("originUser",originUser());
  ret+="    "+RDXmlField("originDateTime",originDateTime());
  ret+="    "+RDXmlField("startPoint",startPoint(RDLogLine::CartPointer),
			 "src=\"cart\"");
  ret+="    "+RDXmlField("startPoint",startPoint(RDLogLine::LogPointer),
			 "src=\"log\"");
  ret+="    "+RDXmlField("endPoint",endPoint(RDLogLine::CartPointer),
			 "src=\"cart\"");
  ret+="    "+RDXmlField("endPoint",endPoint(RDLogLine::LogPointer),
			 "src=\"log\"");
  ret+="    "+RDXmlField("segueStartPoint",
			 segueStartPoint(RDLogLine::CartPointer),
			 "src=\"cart\"");
  ret+="    "+RDXmlField("segueStartPoint",
			 segueStartPoint(RDLogLine::LogPointer),"src=\"log\"");
  ret+="    "+RDXmlField("segueEndPoint",
			 segueEndPoint(RDLogLine::CartPointer),
			 "src=\"cart\"");
  ret+="    "+RDXmlField("segueEndPoint",
			 segueEndPoint(RDLogLine::LogPointer),"src=\"log\"");
  ret+="    "+RDXmlField("segueGain",segueGain());
  ret+="    "+RDXmlField("fadeupPoint",
			 fadeupPoint(RDLogLine::CartPointer),"src=\"cart\"");
  ret+="    "+RDXmlField("fadeupPoint",
			 fadeupPoint(RDLogLine::LogPointer),"src=\"log\"");
  ret+="    "+RDXmlField("fadeupGain",fadeupGain());
  ret+="    "+RDXmlField("fadedownPoint",
			 fadedownPoint(RDLogLine::CartPointer),"src=\"cart\"");
  ret+="    "+RDXmlField("fadedownPoint",
			 fadedownPoint(RDLogLine::LogPointer),"src=\"log\"");
  ret+="    "+RDXmlField("duckUpGain",duckUpGain());
  ret+="    "+RDXmlField("duckDownGain",duckDownGain());
  ret+="    "+RDXmlField("talkStartPoint",talkStartPoint());
  ret+="    "+RDXmlField("talkEndPoint",talkEndPoint());
  ret+="    "+RDXmlField("hookMode",hookMode());
  ret+="    "+RDXmlField("hookStartPoint",hookStartPoint());
  ret+="    "+RDXmlField("hookEndPoint",hookEndPoint());

  ret+="  </logLine>\n";
#endif  // WIN32
  return ret;
}
Exemple #20
0
void helios::api::photograph::install(
        hades::connection& conn,
        atlas::api::server& server
        )
{
    server.install<styx::element, styx::int_type>(
        "photograph_get",
        [&conn](styx::int_type id) {
            auto where = hades::where(
                "helios_photograph.photograph_id = ?",
                hades::row<styx::int_type>(id)
                );
            styx::list l =
                hades::equi_outer_join<helios::photograph, helios::photograph_location>(
                    conn,
                    where
                    );
            if(l.size() != 1)
                throw atlas::api::exception("Photograph not found");

            helios::photograph photograph(l.at(0));

            std::vector<std::string> tags = db::photograph_tags(
                conn,
                photograph.id()
                );

            std::ostringstream oss;
            styx::serialise(
                tags,
                [](const std::string& tag, std::ostream& os) {
                    if(std::find(tag.cbegin(), tag.cend(), ' ') == tag.cend())
                        os << tag;
                    else
                        os << "\"" << tag << "\"";
                },
                " ",
                oss
                );

            atlas::log::information("api::photograph") << "tags " << oss.str();
            photograph.tags() = oss.str();

            return photograph;
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list>(
        "photograph_list",
        boost::bind(
            &hades::equi_outer_join<helios::photograph, helios::photograph_location>,
            boost::ref(conn)
            ),
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::element, styx::element>(
        "photograph_save",
        [&conn](styx::element photograph_e) {
            helios::photograph photograph(photograph_e);
            photograph.save(conn);

            helios::photograph_location photograph_location(photograph);
            photograph_location.save(conn);

            db::set_photograph_tags(conn, photograph.id(), photograph.tags());
            return photograph;
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<bool, styx::element>(
        "photograph_delete",
        [&conn](styx::element photograph_e) {
            helios::photograph photograph(photograph_e);
            hades::devoid(
                "DELETE FROM helios_photograph WHERE photograph_id = ?",
                hades::row<styx::int_type>(
                    photograph.get_int<db::attr::photograph::photograph_id>()
                    ),
                conn
                );
            return true;
        }
        );
    server.install<styx::list>(
        "photograph_recent",
        [&conn]() {
            return hades::get_collection<helios::photograph>(
                conn,
                hades::order_by("helios_photograph.taken DESC", 36)
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list>(
        "photograph_uncategorised",
        [&conn]() {
            // Use a LEFT OUTER JOIN, so photographs without any matching
            // photograph_in_album will have one row with photograph_in_album
            // attributes all NULL.
            return hades::outer_join<helios::photograph, helios::photograph_in_album>(
                conn,
                "helios_photograph.photograph_id = helios_photograph_in_album.photograph_id",
                hades::where("helios_photograph_in_album.photograph_id IS NULL")
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );

    server.install<styx::element, styx::int_type>(
        "album_get",
        [&conn](styx::int_type album_id) {
            helios::album a;
            a.from_id(conn, helios::album::id_type{album_id});
            return a;
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list>(
        "album_list",
        [&conn]() {
            auto ob = hades::order_by("helios_album.name ASC");
            return helios::album::get_collection(conn, ob);
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::element, styx::element>(
        "album_save",
        [&conn](styx::element album_e) {
            helios::album album(album_e);
            album.save(conn);
            return album;
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<bool, styx::element>(
        "album_destroy",
        [&conn](styx::element album_e) {
            helios::album album(album_e);
            return album.destroy(conn);
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<bool, styx::int_type, styx::int_type>(
        "add_photograph_to_album",
        [&conn](styx::int_type photograph_id, styx::int_type album_id) {
            helios::photograph_in_album photograph_in_album(
                helios::photograph_in_album::id_type{photograph_id, album_id}
                );
            return photograph_in_album.save(conn);
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<bool, styx::int_type, styx::int_type>(
        "remove_photograph_from_album",
        [&conn](styx::int_type photograph_id, styx::int_type album_id) {
            helios::photograph_in_album photograph_in_album(
                helios::photograph_in_album::id_type{photograph_id, album_id}
                );
            return photograph_in_album.destroy(conn);
        }/*,*/
        /*boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)*/
        );
    server.install<styx::list, styx::int_type>(
        "photographs_in_album",
        [&conn](int album_id) {
            return hades::join<
                helios::photograph,
                helios::photograph_in_album,
                helios::photograph_location,
                helios::album>(
                conn,
                hades::filter(
                    hades::where(
                        "helios_photograph.photograph_id = helios_photograph_in_album.photograph_id AND "
                        "helios_photograph_in_album.album_id = helios_album.album_id AND "
                        "helios_photograph.photograph_id = helios_photograph_location.photograph_id AND "
                        "helios_album.album_id = ?",
                        hades::row<styx::int_type>(album_id)
                        ),
                    hades::order_by("helios_photograph.taken ASC")
                    )
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list, styx::int_type>(
        "photograph_albums",
        [&conn](int photograph_id) {
            return hades::join<helios::photograph, helios::photograph_in_album, helios::album>(
                conn,
                hades::where(
                    "helios_photograph.photograph_id = helios_photograph_in_album.photograph_id AND "
                    "helios_photograph_in_album.album_id = helios_album.album_id AND "
                    "helios_photograph.photograph_id = ?",
                    hades::row<styx::int_type>(photograph_id)
                    )
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list>(
        "location_list",
        [&conn]() {
            return hades::custom_select<
                helios::location,
                db::attr::location::location,
                db::attr::location::photograph_count>(
                    conn,
                    "SELECT location, COUNT(photograph_id) "
                    " FROM helios_photograph_location "
                    " WHERE location IS NOT NULL AND location != '' "
                    "GROUP BY location ORDER BY location ASC "
                    );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list>(
        "tag_list",
        [&conn]() {
            return hades::custom_select<
                helios::tag,
                db::attr::tag::tag,
                db::attr::tag::photograph_count>(
                    conn,
                    "SELECT tag, COUNT(photograph_id) FROM helios_photograph_tagged "
                    "WHERE tag IS NOT NULL AND tag != '' "
                    "GROUP BY tag ORDER BY tag ASC "
                    );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list, std::string>(
        "photographs_with_tag",
        [&conn](std::string tag) {
            return hades::join<helios::photograph, helios::basic_tag>(
                conn,
                hades::filter(
                    hades::where(
                        "helios_photograph.photograph_id = "
                        " helios_photograph_tagged.photograph_id AND "
                        "helios_photograph_tagged.tag = ? ",
                        hades::row<std::string>(tag)
                        ),
                    hades::order_by("helios_photograph.taken ASC")
                    )
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );
    server.install<styx::list, std::string>(
        "photographs_with_location",
        [&conn](std::string location) {
            return hades::join<helios::photograph, helios::basic_location>(
                conn,
                hades::filter(
                    hades::where(
                        "helios_photograph.photograph_id = "
                        " helios_photograph_location.photograph_id AND "
                        "helios_photograph_location.location = ? ",
                        hades::row<std::string>(location)
                        ),
                    hades::order_by("helios_photograph.taken ASC")
                    )
                );
        },
        boost::bind(atlas::jsonrpc::auth::is_logged_in, boost::ref(conn), _1)
        );

    // JPEG data methods.
    //api_server.install(
        //"insert_jpeg_data",
        //boost::bind(photoalbum::api::insert_jpeg_data, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"jpeg_data",
        //boost::bind(photoalbum::api::jpeg_data, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"jpeg_data_scaled",
        //boost::bind(photoalbum::api::jpeg_data_scaled, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);

    //api_server.install(
        //"locations",
        //boost::bind(photoalbum::api::locations, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"tags",
        //boost::bind(photoalbum::api::tags, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"tags_alphabetical",
        //boost::bind(photoalbum::api::tags_alphabetical, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"tags_popular",
        //boost::bind(photoalbum::api::tags_popular, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);

    // Photograph methods.
    //api_server.install(
        //"photograph",
        //boost::bind(photoalbum::api::get_photograph, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"delete_photograph",
        //boost::bind(photoalbum::api::delete_photograph, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"insert_photograph",
        //boost::bind(photoalbum::api::insert_photograph, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"photograph_albums",
        //boost::bind(photoalbum::api::photograph_albums, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"photograph_list",
        //boost::bind(photoalbum::api::photograph_list, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"photographs_in_album",
        //boost::bind(photoalbum::api::photographs_in_album, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"photographs_with_location",
        //boost::bind(photoalbum::api::photographs_with_location, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"photographs_with_tag",
        //boost::bind(photoalbum::api::photographs_with_tag, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"recent_photographs",
        //boost::bind(photoalbum::api::recent_photographs, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"remove_photograph_from_album",
        //boost::bind(photoalbum::api::remove_photograph_from_album, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"uncategorised_photographs",
        //boost::bind(photoalbum::api::uncategorised_photographs, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"update_photograph",
        //boost::bind(photoalbum::api::update_photograph, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);

    // Note methods.
    //api_server.install(
        //"markdown_data",
        //boost::bind(photoalbum::api::markdown_data, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"note",
        //boost::bind(photoalbum::api::note, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"note_list",
        //boost::bind(photoalbum::api::note_list, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"note_version",
        //boost::bind(photoalbum::api::note_version, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"note_phase_version",
        //boost::bind(photoalbum::api::note_phase_version, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
            //"create_draft_note",
            //boost::bind(photoalbum::api::create_draft_note, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
            //);
    //api_server.install(
        //"delete_note",
        //boost::bind(photoalbum::api::delete_note, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"update_markdown_data",
        //boost::bind(photoalbum::api::update_markdown_data, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"publish_note",
        //boost::bind(photoalbum::api::publish_note, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
    //api_server.install(
        //"published_notes",
        //boost::bind(photoalbum::api::published_notes, _1, _2, boost::ref(db)),
        //boost::bind(jsonrpc::auth::logged_in, boost::ref(auth_db), _1)
        //);
}
Exemple #21
0
QUrl
lastfm::Track::www() const
{
    return UrlBuilder( "music" ).slash( artist( Corrected ) ).slash( album(  Corrected  ).isNull() ? QString("_") : album( Corrected )).slash( title( Corrected ) ).url();
}
Exemple #22
0
void
QueryLabel::mouseMoveEvent( QMouseEvent* event )
{
    QFrame::mouseMoveEvent( event );
    int x = event->x();

    if ( event->buttons() & Qt::LeftButton &&
       ( m_dragPos - event->pos() ).manhattanLength() >= QApplication::startDragDistance() )
    {
        startDrag();
        leaveEvent( 0 );
        return;
    }

    if ( m_query.isNull() && m_result.isNull() )
    {
        m_hoverArea = QRect();
        m_hoverType = None;
        return;
    }

    const QFontMetrics& fm = fontMetrics();
    int dashX = fm.width( DASH );
    int artistX = m_type & Artist ? fm.width( artist() ) : 0;
    int albumX = m_type & Album ? fm.width( album() ) : 0;
    int trackX = m_type & Track ? fm.width( track() ) : 0;

    if ( m_type & Track )
    {
        trackX += contentsMargins().left();
    }
    if ( m_type & Album )
    {
        trackX += albumX + dashX;
        albumX += contentsMargins().left();
    }
    if ( m_type & Artist )
    {
        albumX += artistX + dashX;
        trackX += artistX + dashX;
        artistX += contentsMargins().left();
    }

    QRect hoverArea;
    m_hoverType = None;
    if ( m_type & Artist && x < artistX )
    {
        m_hoverType = Artist;
        hoverArea.setLeft( 0 );
        hoverArea.setRight( artistX + contentsMargins().left() - 1 );
    }
    else if ( m_type & Album && x < albumX && x > artistX )
    {
        m_hoverType = Album;
        int spacing = ( m_type & Artist ) ? dashX : 0;
        hoverArea.setLeft( artistX + spacing );
        hoverArea.setRight( albumX + spacing + contentsMargins().left() - 1 );
    }
    else if ( m_type & Track && x < trackX && x > albumX )
    {
        m_hoverType = Track;
        int spacing = ( m_type & Album ) ? dashX : 0;
        hoverArea.setLeft( albumX + spacing );
        hoverArea.setRight( trackX + contentsMargins().left() - 1 );
    }

    if ( hoverArea.width() )
    {
        hoverArea.setY( 1 );
        hoverArea.setHeight( height() - 2 );
    }
    if ( hoverArea != m_hoverArea )
    {
        m_hoverArea = hoverArea;
        repaint();
    }
}
Exemple #23
0
void
QueryLabel::paintEvent( QPaintEvent* event )
{
    QFrame::paintEvent( event );
    QPainter p( this );
    QRect r = contentsRect();
    QString s = text();
    const QString elidedText = fontMetrics().elidedText( s, mode, r.width() );

    p.save();
    p.setRenderHint( QPainter::Antialiasing );

    if ( m_hoverArea.width() )
    {
        if ( elidedText != s )
        {
            m_hoverArea.setLeft( 0 );
            m_hoverArea.setRight( fontMetrics().width( elidedText ) + contentsMargins().left() * 2 );
            m_hoverType = Track;
        }

        p.setPen( palette().mid().color() );
        p.setBrush( palette().highlight() );
        p.drawRoundedRect( m_hoverArea, 4.0, 4.0 );
    }

    if ( elidedText != s || ( m_result.isNull() && m_query.isNull() ) )
    {
        if ( m_hoverArea.width() )
        {
            p.setPen( palette().highlightedText().color() );
            p.setBrush( palette().highlight() );
        }
        else
        {
            p.setBrush( palette().window() );
            p.setPen( palette().color( foregroundRole() ) );
        }
        p.drawText( r, align, elidedText );
    }
    else
    {
        const QFontMetrics& fm = fontMetrics();
        int dashX = fm.width( DASH );
        int artistX = m_type & Artist ? fm.width( artist() ) : 0;
        int albumX = m_type & Album ? fm.width( album() ) : 0;
        int trackX = m_type & Track ? fm.width( track() ) : 0;

        if ( m_type & Artist )
        {
            p.setBrush( palette().window() );
            p.setPen( palette().color( foregroundRole() ) );

            if ( m_hoverType == Artist )
            {
                p.setPen( palette().highlightedText().color() );
                p.setBrush( palette().highlight() );
            }

            p.drawText( r, align, artist() );
            r.adjust( artistX, 0, 0, 0 );
        }
        if ( m_type & Album )
        {
            p.setBrush( palette().window() );
            p.setPen( palette().color( foregroundRole() ) );

            if ( m_type & Artist )
            {
                p.drawText( r, align, DASH );
                r.adjust( dashX, 0, 0, 0 );
            }
            if ( m_hoverType == Album )
            {
                p.setPen( palette().highlightedText().color() );
                p.setBrush( palette().highlight() );
            }

            p.drawText( r, align, album() );
            r.adjust( albumX, 0, 0, 0 );
        }
        if ( m_type & Track )
        {
            p.setBrush( palette().window() );
            p.setPen( palette().color( foregroundRole() ) );

            if ( m_type & Artist || m_type & Album )
            {
                p.drawText( r, align, DASH );
                r.adjust( dashX, 0, 0, 0 );
            }
            if ( m_hoverType == Track )
            {
                p.setPen( palette().highlightedText().color() );
                p.setBrush( palette().highlight() );
            }

            p.drawText( r, align, track() );
            r.adjust( trackX, 0, 0, 0 );
        }
    }

    p.restore();
}
void XSPFParser::readTrack(QXmlStreamReader & xml, MediaInfo & mediaInfo) const {
	while (!xml.atEnd() && !_stop) {
		xml.readNext();

		QString element(xml.name().toString());

		if (xml.isStartElement()) {

			//Filename
			if (element == XSPF_LOCATION) {
				QUrl url = QUrl::fromEncoded(xml.readElementText().toUtf8());
				QString location(url.toString());
				bool isUrl = MediaInfo::isUrl(location);
				mediaInfo.setUrl(isUrl);
				if (isUrl) {
					mediaInfo.setFileName(location);
				} else {
					QString path(QFileInfo(_filename).path());
					mediaInfo.setFileName(Util::canonicalFilePath(path, location));
				}
			}

			//Unique ID
			else if (element == XSPF_IDENTIFIER) {
				QString identifier(xml.readElementText());
				//FIXME not implemented yet
			}

			//Artist
			else if (element == XSPF_CREATOR) {
				QString creator(xml.readElementText());
				mediaInfo.insertMetadata(MediaInfo::Artist, creator);
			}

			//Album
			else if (element == XSPF_ALBUM) {
				QString album(xml.readElementText());
				mediaInfo.insertMetadata(MediaInfo::Album, album);
			}

			//Track number
			else if (element == XSPF_TRACKNUM) {
				QString trackNum(xml.readElementText());
				mediaInfo.insertMetadata(MediaInfo::TrackNumber, trackNum);
			}

			//Title
			else if (element == XSPF_TITLE) {
				QString title(xml.readElementText());
				mediaInfo.insertMetadata(MediaInfo::Title, title);
			}

			//Comment
			else if (element == XSPF_ANNOTATION) {
				QString annotation(xml.readElementText());
				if (mediaInfo.metadataValue(MediaInfo::Title).isEmpty()) {
					//Some people didn't understand how XSPF works
					//and confused annotation with title
					mediaInfo.insertMetadata(MediaInfo::Title, annotation);
				}
				mediaInfo.insertMetadata(MediaInfo::Comment, annotation);
			}

			//Length
			else if (element == XSPF_DURATION) {
				int duration = xml.readElementText().toInt();
				//XSPF gives us the duration in milliseconds
				//Let's convert it to seconds
				mediaInfo.setLength(duration / 1000);
			}

			//Album art URL
			else if (element == XSPF_IMAGE) {
				QString image(xml.readElementText());
				//FIXME not implemented yet
				//mediaInfo.insertMetadata(MediaInfo::AlbumArt, image);
			}

			//URL of the original web page
			else if (element == XSPF_INFO) {
				QString info(xml.readElementText());
				mediaInfo.insertMetadata(MediaInfo::URL, info);
			}

			//Meta
			else if (element == XSPF_META) {

				//These tags are specific to foobar2000 XSPF plugin

				QXmlStreamAttributes attributes = xml.attributes();

				//Date
				if (attributes.hasAttribute(XSPF_FOOBAR2000_DATE)) {
					QString date(attributes.value(XSPF_FOOBAR2000_DATE).toString());
					mediaInfo.insertMetadata(MediaInfo::Year, date);
				}

				//Genre
				else if (attributes.hasAttribute(XSPF_FOOBAR2000_GENRE)) {
					QString genre(attributes.value(XSPF_FOOBAR2000_GENRE).toString());
					mediaInfo.insertMetadata(MediaInfo::Genre, genre);
				}
			}

			else if (element == XSPF_EXTENSION) {
				QString xspfNamespace(xml.attributes().value(XSPF_APPLICATION).toString());

				if (xspfNamespace == XSPF_QUARKPLAYER_NAMESPACE) {
					while (!xml.atEnd() && !_stop) {
						xml.readNext();

						QString extensionElement(xml.name().toString());
						if (xml.isStartElement()) {

							if (extensionElement == XSPF_QUARKPLAYER_CUE_START_INDEX) {
								QString cueStartIndex(xml.readElementText());
								mediaInfo.setCueStartIndex(cueStartIndex);
							}

							else if (extensionElement == XSPF_QUARKPLAYER_CUE_END_INDEX) {
								QString cueEndIndex(xml.readElementText());
								mediaInfo.setCueEndIndex(cueEndIndex);
							}

							else if (extensionElement == XSPF_QUARKPLAYER_YEAR) {
								QString year(xml.readElementText());
								mediaInfo.insertMetadata(MediaInfo::Year, year);
							}

							else if (extensionElement == XSPF_QUARKPLAYER_GENRE) {
								QString genre(xml.readElementText());
								mediaInfo.insertMetadata(MediaInfo::Genre, genre);
							}
						}

						if (xml.isEndElement()) {
							if (extensionElement == XSPF_EXTENSION) {
								break;
							}
						}
					}
				}
			}
		}

		if (xml.isEndElement()) {
			if (element == XSPF_TRACK) {
				return;
			}
		}
	}
}
Exemple #25
0
void
MetadataEditor::writeMetadata( bool closeDlg )
{
    if ( m_result )
    {
        QFileInfo fi( QUrl( m_result->url() ).toLocalFile() );

        bool changed = false;
        QByteArray fileName = QFile::encodeName( fi.canonicalFilePath() );
#ifdef Q_OS_WIN
        const wchar_t* encodedName = fi.canonicalFilePath().toStdWString().c_str();
#else
        const char* encodedName = fileName.constData();
#endif

        TagLib::FileRef f( encodedName );
        QSharedPointer<Tomahawk::Tag> tag( Tomahawk::Tag::fromFile( f ) );

        if ( title() != m_result->track()->track() )
        {
            tDebug() << Q_FUNC_INFO << "Track changed" << title() << m_result->track();

            tag->setTitle( title() );
            m_result->track()->setTrack( title() );

            changed = true;
        }

        Tomahawk::artist_ptr newArtist = Tomahawk::Artist::get( artist(), true );
        if ( newArtist != m_result->track()->artistPtr() )
        {
            tDebug() << Q_FUNC_INFO << "Artist changed" << artist() << m_result->track()->artist();

            tag->setArtist( artist() );
            m_result->track()->setArtist( artist() );

            changed = true;
        }

        Tomahawk::album_ptr newAlbum = Tomahawk::Album::get( newArtist, album(), true );
        if ( newAlbum != m_result->track()->albumPtr() )
        {
            tDebug() << Q_FUNC_INFO << "Album changed" << album() << newAlbum->id() << m_result->track()->album() << m_result->track()->albumPtr()->id() << newAlbum.data() << m_result->track()->albumPtr().data();
            if ( newAlbum->id() != m_result->track()->albumPtr()->id() )
            {
                tag->setAlbum( album() );
                m_result->track()->setAlbum( album() );

                changed = true;
            }
        }

        // FIXME: Ugly workaround for the min value of 0
        if ( albumPos() != 0 && albumPos() != (int)m_result->track()->albumpos() )
        {
            tag->setTrack( albumPos() );
            m_result->track()->setAlbumPos( albumPos() );

            tDebug() << Q_FUNC_INFO << "Albumpos changed";
            changed = true;
        }

        // FIXME: Ugly workaround for the min value of 1900
        if ( year() != 1900 && year() != m_result->track()->year() )
        {
            tag->setYear( year() );
            {
                QVariantMap attr = m_result->track()->attributes();
                attr[ "releaseyear" ] = year();
                m_result->track()->setAttributes( attr );
            }

            tDebug() << Q_FUNC_INFO << "Year changed";
            changed = true;
        }

        if ( changed )
        {
            f.save();

            m_editFiles.append( fileName );
            m_result->doneEditing();

            tDebug() << Q_FUNC_INFO << m_result->toString() << m_result->track()->toString();
        }
    }

    if ( closeDlg )
    {
        if ( m_editFiles.count() )
            ScanManager::instance()->runFileScan( m_editFiles, false );

        close();
    }
}
Exemple #26
0
bool ID3v1Tag::read ( XMP_IO* file, SXMPMeta* meta )
{
	// Returns true if ID3v1 (or v1.1) exists, otherwise false, sets XMP properties en route.

	if ( file->Length() <= 128 ) return false;  // ensure sufficient room
	file->Seek ( -128, kXMP_SeekFromEnd );

	XMP_Uns32 tagID = XIO::ReadInt32_BE ( file );
	tagID = tagID & 0xFFFFFF00; // wipe 4th byte
	if ( tagID != 0x54414700 ) return false; // must be "TAG"
	file->Seek ( -1, kXMP_SeekFromCurrent  ); //rewind 1

	XMP_Uns8 buffer[31]; // nothing is bigger here, than 30 bytes (offsets [0]-[29])
	buffer[30] = 0;		 // wipe last byte
	std::string utf8string;

	file->ReadAll ( buffer, 30 );
	std::string title ( (char*) buffer ); //security: guaranteed to 0-terminate after 30 bytes
	if ( ! title.empty() ) {
		ReconcileUtils::Latin1ToUTF8 ( title.c_str(), title.size(), &utf8string );
		meta->SetLocalizedText ( kXMP_NS_DC, "title", "", "x-default", utf8string.c_str() );
	}

	file->ReadAll ( buffer, 30 );
	std::string artist( (char*) buffer );
	if ( ! artist.empty() ) {
		ReconcileUtils::Latin1ToUTF8 ( artist.c_str(), artist.size(), &utf8string );
		meta->SetProperty ( kXMP_NS_DM, "artist", utf8string.c_str() );
	}

	file->ReadAll ( buffer, 30 );
	std::string album( (char*) buffer );
	if ( ! album.empty() ) {
		ReconcileUtils::Latin1ToUTF8 ( album.c_str(), album.size(), &utf8string );
		meta->SetProperty ( kXMP_NS_DM, "album", utf8string.c_str() );
	}

	file->ReadAll ( buffer, 4 );
	buffer[4]=0; // ensure 0-term
	std::string year( (char*) buffer );
	if ( ! year.empty() ) {	// should be moot for a year, but let's be safe:
		ReconcileUtils::Latin1ToUTF8 ( year.c_str(), year.size(), &utf8string );
		meta->SetProperty ( kXMP_NS_XMP, "CreateDate",  utf8string.c_str() );
	}

	file->ReadAll ( buffer, 30 );
	std::string comment( (char*) buffer );
	if ( ! comment.empty() ) {
		ReconcileUtils::Latin1ToUTF8 ( comment.c_str(), comment.size(), &utf8string );
		meta->SetProperty ( kXMP_NS_DM, "logComment", utf8string.c_str() );
	}

	if ( buffer[28] == 0 ) {
		XMP_Uns8 trackNo = buffer[29];
		if ( trackNo > 0 ) {
			std::string trackStr;
			meta->SetProperty_Int ( kXMP_NS_DM, "trackNumber", trackNo );
		}
	}

	XMP_Uns8 genreNo = XIO::ReadUns8 ( file );
	if ( genreNo < numberedGenreCount ) {
		meta->SetProperty ( kXMP_NS_DM, "genre", kNumberedGenres[genreNo].name );
	} else {
		char buffer[4];	// AUDIT: Big enough for UInt8.
		snprintf ( buffer, 4, "%d", genreNo );
		XMP_Assert ( strlen(buffer) == 3 );	// Should be in the range 126..255.
		meta->SetProperty ( kXMP_NS_DM, "genre", buffer );
	}

	return true; // ID3Tag found

}	// ID3v1Tag::read
Exemple #27
0
qint32 cMediaInfo::writeFilename()
{
	QSqlQuery	query;

	query.prepare("SELECT id FROM file WHERE fileName=:fileName AND fileSize=:fileSize AND fileDate=:fileDate;");
	query.bindValue(":fileName", fileName());
	query.bindValue(":fileSize", fileSize());
	query.bindValue(":fileDate", fileDate());

	if(!query.exec())
	{
		myDebug << query.lastError().text();
		return(-1);
	}

	if(query.next())
		query.prepare("UPDATE file SET fileType=:fileType, length=:length, bitrate=:bitrate, sampleRate=:sampleRate, channels=:channels, bitsPerSample=:bitsPerSample, layer=:layer, version=:version, sampleWidth=:sampleWidth, sampleFrames=:sampleFrames, isEncrypted=:isEncrypted, trackGain=:trackGain, albumGain=:albumGain, trackPeak=:trackPeak, albumPeak=:albumPeak, protectionEnabled=:protectionEnabled, channelMode=:channelMode, isCopyrighted=:isCopyrighted, isOriginal=:isOriginal, album=:album, title=:title, copyright=:copyright, trackNumber=:trackNumber, contentGroupDescription=:contentGroupDescription, subTitle=:subTitle, originalAlbum=:originalAlbum, partOfSet=:partOfSet, subTitleOfSet=:subTitleOfSet, internationalStandardRecordingCode=:internationalStandardRecordingCode, leadArtist=:leadArtist, band=:band, conductor=:conductor, interpret=:interpret, originalArtist=:originalArtist, textWriter=:textWriter, originalTextWriter=:originalTextWriter, composer=:composer, encodedBy=:encodedBy, beatsPerMinute=:beatsPerMinute, language=:language, contentType=:contentType, mediaType=:mediaType, mood=:mood, producedNotice=:producedNotice, publisher=:publisher, fileOwner=:fileOwner, internetRadioStationName=:internetRadioStationName, internetRadioStationOwner=:internetRadioStationOwner, originalFilename=:originalFilename, playlistDelay=:playlistDelay, encodingTime=:encodingTime, originalReleaseTime=:originalReleaseTime, recordingTime=:recordingTime, releaseTime=:releaseTime, taggingTime=:taggingTime, swhwSettings=:swhwSettings, albumSortOrder=:albumSortOrder, performerSortOrder=:performerSortOrder, titleSortOrder=:titleSortOrder, synchronizedLyrics=:synchronizedLyrics, unsynchronizedLyrics=:unsynchronizedLyrics WHERE filename=:filename AND filesize=:filesize AND filedate=:filedate;");
	else
		query.prepare("INSERT INTO file (fileName, fileSize, fileDate, fileType, length, bitrate, sampleRate, channels, bitsPerSample, layer, version, sampleWidth, sampleFrames, isEncrypted, trackGain, albumGain, trackPeak, albumPeak, protectionEnabled, channelMode, isCopyrighted, isOriginal, album, title, copyright, trackNumber, contentGroupDescription, subTitle, originalAlbum, partOfSet, subTitleOfSet, internationalStandardRecordingCode, leadArtist, band, conductor, interpret, originalArtist, textWriter, originalTextWriter, composer, encodedBy, beatsPerMinute, language, contentType, mediaType, mood, producedNotice, publisher, fileOwner, internetRadioStationName, internetRadioStationOwner, originalFilename, playlistDelay, encodingTime, originalReleaseTime, recordingTime, releaseTime, taggingTime, swhwSettings, albumSortOrder, performerSortOrder, titleSortOrder, synchronizedLyrics, unsynchronizedLyrics) VALUES (:fileName, :fileSize, :fileDate, :fileType, :length, :bitrate, :sampleRate, :channels, :bitsPerSample, :layer, :version, :sampleWidth, :sampleFrames, :isEncrypted, :trackGain, :albumGain, :trackPeak, :albumPeak, :protectionEnabled, :channelMode, :isCopyrighted, :isOriginal, :album, :title, :copyright, :trackNumber, :contentGroupDescription, :subTitle, :originalAlbum, :partOfSet, :subTitleOfSet, :internationalStandardRecordingCode, :leadArtist, :band, :conductor, :interpret, :originalArtist, :textWriter, :originalTextWriter, :composer, :encodedBy, :beatsPerMinute, :language, :contentType, :mediaType, :mood, :producedNotice, :publisher, :fileOwner, :internetRadioStationName, :internetRadioStationOwner, :originalFilename, :playlistDelay, :encodingTime, :originalReleaseTime, :recordingTime, :releaseTime, :taggingTime, :swhwSettings, :albumSortOrder, :performerSortOrder, :titleSortOrder, :synchronizedLyrics, :unsynchronizedLyrics);");

	query.bindValue(":fileName", fileName());
	query.bindValue(":fileSize", fileSize());
	query.bindValue(":fileDate", fileDate());
	query.bindValue(":fileType", fileType());
	query.bindValue(":length", length());
	query.bindValue(":bitrate", bitrate());
	query.bindValue(":sampleRate", sampleRate());
	query.bindValue(":channels", channels());
	query.bindValue(":bitsPerSample", bitsPerSample());
	query.bindValue(":layer", layer());
	query.bindValue(":version", version());
	query.bindValue(":sampleWidth", sampleWidth());
	query.bindValue(":sampleFrames", sampleFrames());
	query.bindValue(":isEncrypted", isEncrypted());
	query.bindValue(":trackGain", trackGain());
	query.bindValue(":albumGain", albumGain());
	query.bindValue(":trackPeak", trackPeak());
	query.bindValue(":albumPeak", albumPeak());
	query.bindValue(":protectionEnabled", protectionEnabled());
	query.bindValue(":channelMode", channelMode());
	query.bindValue(":isCopyrighted", isCopyrighted());
	query.bindValue(":isOriginal", isOriginal());
	query.bindValue(":album", album());
	query.bindValue(":title", title());
	query.bindValue(":copyright", copyright());
	query.bindValue(":trackNumber", trackNumber());
	query.bindValue(":contentGroupDescription", contentGroupDescription());
	query.bindValue(":subTitle", subTitle());
	query.bindValue(":originalAlbum", originalAlbum());
	query.bindValue(":partOfSet", partOfSet());
	query.bindValue(":subTitleOfSet", subTitleOfSet());
	query.bindValue(":internationalStandardRecordingCode", internationalStandardRecordingCode());
	query.bindValue(":leadArtist", leadArtist());
	query.bindValue(":band", band());
	query.bindValue(":conductor", conductor());
	query.bindValue(":interpret", interpret().join(", "));
	query.bindValue(":originalArtist", originalArtist());
	query.bindValue(":textWriter", textWriter());
	query.bindValue(":originalTextWriter", originalTextWriter());
	query.bindValue(":composer", composer());
	query.bindValue(":encodedBy", encodedBy());
	query.bindValue(":beatsPerMinute", beatsPerMinute());
	query.bindValue(":language", language().join(", "));
	query.bindValue(":contentType", contentType().join(", "));
	query.bindValue(":mediaType", mediaType().join(", "));
	query.bindValue(":mood", mood());
	query.bindValue(":producedNotice", producedNotice());
	query.bindValue(":publisher", publisher());
	query.bindValue(":fileOwner", fileOwner());
	query.bindValue(":internetRadioStationName", internetRadioStationName());
	query.bindValue(":internetRadioStationOwner", internetRadioStationOwner());
	query.bindValue(":originalFilename", originalFilename());
	query.bindValue(":playlistDelay", playlistDelay());
	query.bindValue(":encodingTime", encodingTime());
	query.bindValue(":originalReleaseTime", originalReleaseTime());
	query.bindValue(":recordingTime", recordingTime());
	query.bindValue(":releaseTime", releaseTime());
	query.bindValue(":taggingTime", taggingTime());
	query.bindValue(":swhwSettings", swhwSettings().join(", "));
	query.bindValue(":albumSortOrder", albumSortOrder());
	query.bindValue(":performerSortOrder", performerSortOrder());
	query.bindValue(":titleSortOrder", titleSortOrder());
	query.bindValue(":synchronizedLyrics", synchronizedLyrics().join());
	query.bindValue(":unsynchronizedLyrics", unsynchronizedLyrics().join("||"));

	if(!query.exec())
	{
		myDebug << query.lastError().text();
		return(-1);
	}

	query.prepare("SELECT id FROM file WHERE fileName=:fileName AND fileSize=:fileSize AND fileDate=:fileDate;");
	query.bindValue(":fileName", fileName());
	query.bindValue(":fileSize", fileSize());
	query.bindValue(":fileDate", fileDate());

	if(!query.exec())
	{
		myDebug << query.lastError().text();
		return(-1);
	}

	if(query.next())
		return(query.value("id").toInt());

	return(-1);
}
void import_flac_file(const std::string& filename)
{
  //std::cerr << "import_flac_file " << filename << std::endl;

  TagLib::FLAC::File file(filename.c_str());

  auto tag = file.tag();

  auto artist_name = tag->artist().to8Bit(true);
  auto album_title = tag->album().to8Bit(true);
  auto track_title = tag->title().to8Bit(true);

  auto artist = dm::artist::find_by_name(artist_name);

  if ( artist.is_null() )
  {
    // Create artist.
    artist.name(artist_name);
    artist.save();
  }

  auto album = artist.find_album_by_title(album_title);

  if ( album.is_null() )
  {
    // Create album.
    album.title(album_title);
    album.member("artist", json::object{ { "id", artist.id() }, { "name", artist.name() } });
    album.save();

    // Add album to artist albums.
    artist.add_album(album);
    artist.save();
  }

  auto track = album.find_track_by_title_and_number(track_title, tag->track());

  // Set/update track attributes.

  track.title(track_title);
  track.track_number(tag->track());
  track.disc_number(1);

  // Create track source object.
  json::object source{ { "name", "local" }, { "uri", filename } };

  TagLib::FLAC::Properties* properties = file.audioProperties();
  if ( properties )
  {
    track.duration(properties->length());
  }

  TagLib::Ogg::XiphComment* xiph_comment = file.xiphComment();
  if ( xiph_comment )
  {
    auto field_map = xiph_comment->fieldListMap();

    json::object replaygain;

    for ( auto& field : field_map )
    {
      if ( field.first == "TRACK NUMBER" || field.first == "TRACKNUMBER" )
      {
        if ( field.second.size() > 0 ) {
          track.track_number(std::stoi(field.second[0].to8Bit()));
        }
        else {
          std::cerr << "field='" << field.first << "' string list size=" << field.second.size() << std::endl;
        }
      }
      else if ( field.first == "DISC NUMBER" || field.first == "DISCNUMBER" )
      {
        if ( field.second.size() > 0 ) {
          track.disc_number(std::stoi(field.second[0].to8Bit()));
        }
        else {
          std::cerr << "field='" << field.first << "' string list size=" << field.second.size() << std::endl;
        }
      }
      else if ( field.first == "REPLAYGAIN_REFERENCE_LOUDNESS" )
      {
        auto ref_loudness = std::stod(field.second[0].to8Bit());
        replaygain["reference_loudness"] = ref_loudness;
      }
      else if ( field.first == "REPLAYGAIN_TRACK_GAIN" )
      {
        auto gain = std::stod(field.second[0].to8Bit());
        replaygain["track_gain"] = gain;
      }
    }

    if ( !replaygain.empty() ) {
      source["replaygain"] = replaygain;
    }
  }

  const TagLib::List<TagLib::FLAC::Picture*>& images = file.pictureList();

  if ( images.size() > 0 )
  {
    TagLib::FLAC::Picture* image = images[0];

    if ( image->mimeType() == "image/jpeg" )
    {
      auto cover = dm::album_cover::find_by_album_id(album.id());

      if ( cover.is_null() )
      {
        cover.format("jpg");
        cover.data(reinterpret_cast<const char*>(image->data().data()), image->data().size());
        cover.save();
      }
    }
    else
    {
      std::cerr << "unhandled image mime type - " << filename << " images=" << images.size() << ", mime type " << image->mimeType() << std::endl;
    }
  }

  track.artist(artist);
  track.album(album);
  track.source(std::move(source));

  if ( track.id_is_null() )
  {
    // Create track id.
    track.save();
    // Add new track to album.
    album.add_track(track);
    album.save();
  }
  else
  {
    track.save();
  }
}