X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?p=staging%2Fsoundmanager.git;a=blobdiff_plain;f=sample%2Fmediaplayer%2Fapp%2Fplaylistwithmetadata.cpp;fp=sample%2Fmediaplayer%2Fapp%2Fplaylistwithmetadata.cpp;h=9e2e614b93d95706b96c9d8b6c3ba684245a6940;hp=0000000000000000000000000000000000000000;hb=2e602801b372b0b68111316b89f567213e3ea378;hpb=f743c3428f41b8d127e538ea8a6505a0c882cdb2 diff --git a/sample/mediaplayer/app/playlistwithmetadata.cpp b/sample/mediaplayer/app/playlistwithmetadata.cpp new file mode 100644 index 0000000..9e2e614 --- /dev/null +++ b/sample/mediaplayer/app/playlistwithmetadata.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2016 The Qt Company Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "playlistwithmetadata.h" + +#include +#include +#include +#include +#include +#include + +class PlaylistWithMetadata::Private +{ +public: + Private(PlaylistWithMetadata *parent); + + void disconnect(); + void connect(); + +private: + void loadMetadata(int row); + +private: + PlaylistWithMetadata *q; + +public: + QAbstractListModel *source; + QList connections; + QList urls; + QHash title; + QHash artist; + QHash coverArt; + QHash duration; + QHash players; +}; + +PlaylistWithMetadata::Private::Private(PlaylistWithMetadata *parent) + : q(parent) + , source(nullptr) +{ +} + +void PlaylistWithMetadata::Private::disconnect() +{ + if (source) { + for (const auto &connection : connections) + q->disconnect(connection); + connections.clear(); + } +} + +void PlaylistWithMetadata::Private::connect() +{ + if (source) { + connections.append(q->connect(source, &QAbstractListModel::rowsAboutToBeInserted, [&](const QModelIndex &parent, int first, int last) { + Q_UNUSED(parent) + q->beginInsertRows(QModelIndex(), first, last); + })); + connections.append(q->connect(source, &QAbstractListModel::rowsInserted, [&](const QModelIndex &parent, int first, int last) { + Q_UNUSED(parent) + for (int i = first; i <= last; i++) { + loadMetadata(i); + } + q->endInsertRows(); + })); + + connections.append(q->connect(source, &QAbstractListModel::rowsAboutToBeRemoved, [&](const QModelIndex &parent, int first, int last) { + Q_UNUSED(parent) + q->beginRemoveRows(QModelIndex(), first, last); + })); + connections.append(q->connect(source, &QAbstractListModel::rowsRemoved, [&](const QModelIndex &parent, int first, int last) { + Q_UNUSED(parent) + for (int i = last; i >= first; --i) { + QUrl url = urls.at(i); + urls.removeAt(i); + + players.remove(url); + title.remove(url); + artist.remove(url); + coverArt.remove(url); + duration.remove(url); + } + q->endRemoveRows(); + })); + + int count = source->rowCount(); + if (count > 0) { + q->beginInsertRows(QModelIndex(), 0, count); + for (int i = 0; i < count; i++) { + loadMetadata(i); + } + q->endInsertRows(); + } + } +} + +void PlaylistWithMetadata::Private::loadMetadata(int row) +{ + QUrl url = source->data(source->index(row), Qt::UserRole + 1).toUrl(); + QMediaPlayer *player = new QMediaPlayer(q); + urls.append(url); + players.insert(url, player); + q->connect(player, &QMediaPlayer::mediaStatusChanged, [this, url](QMediaPlayer::MediaStatus mediaStatus) { + switch (mediaStatus) { + case QMediaPlayer::NoMedia: + case QMediaPlayer::LoadedMedia: { + QMediaPlayer *player = players.take(url); + title.insert(url, player->metaData(QMediaMetaData::Title).toString()); + artist.insert(url, player->metaData(QMediaMetaData::ContributingArtist).toString()); + QVariant coverArtImage = player->metaData(QMediaMetaData::CoverArtImage); + if (coverArtImage.type() == QVariant::Image) { + QImage image = coverArtImage.value(); + QByteArray data; + QBuffer buffer(&data); + buffer.open(QBuffer::WriteOnly); + QImageWriter png(&buffer, "png"); + if (png.write(image)) { + buffer.close(); + coverArt.insert(url, QUrl(QStringLiteral("data:image/png;base64,") + data.toBase64())); + } + } + duration.insert(url, player->duration()); + QModelIndex index = q->index(urls.indexOf(url)); + q->dataChanged(index, index, QVector() << TitleRole << ArtistRole << CoverArtRole << DurationRole); + player->deleteLater(); + break; } + default: + break; + } + + }); + player->setMedia(url); +} + +PlaylistWithMetadata::PlaylistWithMetadata(QObject *parent) + : QAbstractListModel(parent) + , d(new Private(this)) +{ +} + +PlaylistWithMetadata::~PlaylistWithMetadata() +{ + delete d; +} + +int PlaylistWithMetadata::rowCount(const QModelIndex &parent) const +{ + int ret = 0; + if (parent.isValid()) + return ret; + if (d->source) + ret = d->source->rowCount(QModelIndex()); + return ret; +} + +QVariant PlaylistWithMetadata::data(const QModelIndex &index, int role) const +{ + QVariant ret; + if (!index.isValid()) + return ret; + int row = index.row(); + if (row < 0 || rowCount() <= row) + return ret; + QUrl url = d->urls.at(row); + switch (role) { + case TitleRole: + ret = d->title.value(url); + if (ret.toString().isEmpty()) + ret = QVariant(url.fileName()); + break; + case ArtistRole: + ret = d->artist.value(url); + break; + case CoverArtRole: + ret = d->coverArt.value(url); + break; + case SourceRole: + ret = url; + break; + case DurationRole: + ret = d->duration.value(url); + break; + default: + qWarning() << role; + } + + return ret; +} + +QHash PlaylistWithMetadata::roleNames() const +{ + return { + {TitleRole, "title"}, + {ArtistRole, "artist"}, + {CoverArtRole, "coverArt"}, + {SourceRole, "source"}, + {DurationRole, "duration"} + }; +} + +QAbstractListModel *PlaylistWithMetadata::source() const +{ + return d->source; +} + +void PlaylistWithMetadata::setSource(QAbstractListModel *source) +{ + if (d->source == source) return; + d->disconnect(); + d->source = source; + d->connect(); + emit sourceChanged(source); +}