@@ -0,0 +1,288 @@
2+ * Copyright (C) 2013 Canonical, Ltd.
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ * Author: Michael Zanetti <michael.zanetti@canonical.com>
19+#include "mediaplayer.h"
24+class MetaDataObject: public QObject
27+ Q_PROPERTY(QVariant title READ title NOTIFY metaDataChanged)
28+ Q_PROPERTY(QVariant resolution READ resolution NOTIFY metaDataChanged)
30+ MetaDataObject(MediaPlayer* parent = nullptr)
36+ QVariant title() const { return getProperty("title"); }
37+ QVariant resolution() const { return getProperty("resolution", QSize(160, 90)); }
39+ QVariant getProperty(const QString& property, QVariant defaultValue = QVariant()) const {
40+ MediaDataSource* sourceData = MediaPlayerDataController::instance()->dataForSource(m_source->source());
41+ QVariant metaData = sourceData->metaData();
42+ return metaData.toMap().value(property, defaultValue);
46+ void metaDataChanged();
49+ MediaPlayer* m_source;
52+MediaPlayer::MediaPlayer(QObject* parent)
54+ , m_playbackState(StoppedState)
56+ , m_metaData(new MetaDataObject(this))
58+ qsrand(time(nullptr));
59+ m_timer.setInterval(100);
60+ connect(&m_timer, SIGNAL(timeout()), SLOT(timerEvent()));
62+ connect(MediaPlayerDataController::instance(), &MediaPlayerDataController::sourceRemoved,
63+ this, [this](const QUrl&) {
64+ disconnect(0, &MediaDataSource::durationChanged, this, &MediaPlayer::durationChanged);
65+ disconnect(0, &MediaDataSource::seekableChanged, this, &MediaPlayer::seekableChanged);
66+ disconnect(0, &MediaDataSource::availabilityChanged, this, &MediaPlayer::availabilityChanged);
69+ connect(MediaPlayerDataController::instance(), &MediaPlayerDataController::sourceAdded,
70+ this, [this](const QUrl& source) {
71+ MediaDataSource* dataSource = MediaPlayerDataController::instance()->dataForSource(source);
72+ if (!dataSource) return;
74+ connect(dataSource, &MediaDataSource::durationChanged, this, &MediaPlayer::durationChanged);
75+ connect(dataSource, &MediaDataSource::seekableChanged,this, &MediaPlayer::seekableChanged);
76+ connect(dataSource, &MediaDataSource::availabilityChanged,this, &MediaPlayer::availabilityChanged);
80+QUrl MediaPlayer::source() const
85+void MediaPlayer::setSource(const QUrl &source)
87+ if (m_source != source) {
89+ Q_EMIT sourceChanged(source);
90+ Q_EMIT durationChanged(duration());
91+ Q_EMIT seekableChanged(isSeekable());
92+ Q_EMIT availabilityChanged(availability());
95+ Q_EMIT positionChanged(m_position);
97+ m_status = availability()==Available ? Loaded : InvalidMedia;
98+ Q_EMIT statusChanged();
102+MediaPlayer::PlaybackState MediaPlayer::playbackState() const
104+ return m_playbackState;
107+int MediaPlayer::position() const
112+int MediaPlayer::duration() const
114+ MediaDataSource* dataSource = MediaPlayerDataController::instance()->dataForSource(source());
115+ if (dataSource) return dataSource->duration();
119+QString MediaPlayer::errorString() const
124+void MediaPlayer::pause()
126+ if (m_playbackState == PlayingState) {
127+ m_playbackState = PausedState;
128+ Q_EMIT playbackStateChanged(m_playbackState);
133+void MediaPlayer::play()
135+ if (m_playbackState != PlayingState) {
136+ m_playbackState = PlayingState;
137+ Q_EMIT playbackStateChanged(m_playbackState);
143+void MediaPlayer::stop()
145+ if (m_playbackState != StoppedState) {
146+ m_playbackState = StoppedState;
147+ Q_EMIT playbackStateChanged(m_playbackState);
150+ Q_EMIT positionChanged(m_position);
154+void MediaPlayer::seek(int position)
156+ if (status() != Loaded) return;
157+ int newPosition = qMin(qMax(0, position), duration());
158+ if (newPosition != m_position) {
159+ m_position = newPosition;
160+ Q_EMIT positionChanged(m_position);
165+void MediaPlayer::timerEvent()
167+ if (m_position + m_timer.interval() < duration()) {
168+ m_position += m_timer.interval();
169+ Q_EMIT positionChanged(m_position);
175+MediaPlayer::AudioRole MediaPlayer::audioRole() const
177+ return MediaPlayer::MultimediaRole;
180+void MediaPlayer::setAudioRole(MediaPlayer::AudioRole audioRole)
182+ Q_UNUSED(audioRole);
185+bool MediaPlayer::isSeekable() const
187+ MediaDataSource* dataSource = MediaPlayerDataController::instance()->dataForSource(source());
188+ if (dataSource) return dataSource->isSeekable();
192+MediaPlayer::Availability MediaPlayer::availability() const
194+ MediaDataSource* dataSource = MediaPlayerDataController::instance()->dataForSource(source());
195+ if (dataSource) return dataSource->availability();
200+MediaDataSource::MediaDataSource(QObject *parent)
203+ , m_duration((qrand() % 20000) + 10000)
204+ , m_availability(MediaPlayer::Available)
208+MediaDataSource::~MediaDataSource()
210+ if (!m_source.isEmpty()) MediaPlayerDataController::instance()->unregisterDataSource(this);
213+void MediaDataSource::setSource(const QUrl &source)
215+ if (m_source != source) {
216+ if (!m_source.isEmpty()) MediaPlayerDataController::instance()->unregisterDataSource(this);
220+ if (!m_source.isEmpty()) MediaPlayerDataController::instance()->registerDataSource(this);
221+ Q_EMIT sourceChanged();
225+void MediaDataSource::setSeekable(bool seekable)
227+ if (m_seekable != seekable) {
228+ m_seekable = seekable;
229+ Q_EMIT seekableChanged(m_seekable);
233+void MediaDataSource::setDuration(int duration)
235+ if (m_duration != duration) {
236+ m_duration = duration;
237+ Q_EMIT durationChanged(m_duration);
241+void MediaDataSource::setAvailability(MediaPlayer::Availability availability)
243+ if (m_availability != availability) {
244+ m_availability = availability;
245+ Q_EMIT availabilityChanged(m_availability);
249+void MediaDataSource::setMetaData(const QVariant& metaData)
251+ if (m_metaData != metaData) {
252+ m_metaData = metaData;
253+ Q_EMIT metaDataChanged();
257+MediaPlayerDataController *MediaPlayerDataController::instance()
259+ static MediaPlayerDataController* instance = nullptr;
260+ if (!instance) { instance = new MediaPlayerDataController(); }
264+void MediaPlayerDataController::registerDataSource(MediaDataSource *dataSource)
266+ m_dataSources[dataSource->source()] = dataSource;
267+ Q_EMIT sourceAdded(dataSource->source());
270+void MediaPlayerDataController::unregisterDataSource(MediaDataSource *dataSource)
272+ QList<QUrl> keys = m_dataSources.keys(dataSource);
273+ Q_FOREACH(const QUrl& key, keys) {
274+ m_dataSources.remove(key);
275+ Q_EMIT sourceRemoved(key);
279+MediaDataSource *MediaPlayerDataController::dataForSource(const QUrl &source)
281+ if (!m_dataSources.contains(source)) {
282+ static MediaDataSource defaultSource;
283+ return &defaultSource;
285+ return m_dataSources[source];
288+#include "mediaplayer.moc"