1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qdeclarativeplaylist_p.h"
41
42QT_BEGIN_NAMESPACE
43
44/*!
45 \qmltype PlaylistItem
46 \instantiates QDeclarativePlaylistItem
47 \since 5.6
48
49 \inqmlmodule QtMultimedia
50 \ingroup multimedia_qml
51 \ingroup multimedia_audio_qml
52 \ingroup multimedia_video_qml
53 \brief Defines an item in a Playlist.
54
55 \sa Playlist
56*/
57
58/*!
59 \qmlproperty url QtMultimedia::PlaylistItem::source
60
61 This property holds the source URL of the item.
62
63 \sa Playlist
64*/
65QDeclarativePlaylistItem::QDeclarativePlaylistItem(QObject *parent)
66 : QObject(parent)
67{
68}
69
70QUrl QDeclarativePlaylistItem::source() const
71{
72 return m_source;
73}
74
75void QDeclarativePlaylistItem::setSource(const QUrl &source)
76{
77 m_source = source;
78}
79
80/*!
81 \qmltype Playlist
82 \instantiates QDeclarativePlaylist
83 \since 5.6
84 \brief For specifying a list of media to be played.
85
86 \inqmlmodule QtMultimedia
87 \ingroup multimedia_qml
88 \ingroup multimedia_audio_qml
89 \ingroup multimedia_video_qml
90
91 The Playlist type provides a way to play a list of media with the MediaPlayer, Audio and Video
92 types. It can be used as a data source for view elements (such as ListView) and other elements
93 that interact with model data (such as Repeater). When used as a data model, each playlist
94 item's source URL can be accessed using the \c source role.
95
96 \qml
97 Item {
98 width: 400;
99 height: 300;
100
101 Audio {
102 id: player;
103 playlist: Playlist {
104 id: playlist
105 PlaylistItem { source: "song1.ogg"; }
106 PlaylistItem { source: "song2.ogg"; }
107 PlaylistItem { source: "song3.ogg"; }
108 }
109 }
110
111 ListView {
112 model: playlist;
113 delegate: Text {
114 font.pixelSize: 16;
115 text: source;
116 }
117 }
118
119 MouseArea {
120 anchors.fill: parent;
121 onPressed: {
122 if (player.playbackState != Audio.PlayingState) {
123 player.play();
124 } else {
125 player.pause();
126 }
127 }
128 }
129 }
130 \endqml
131
132 \sa MediaPlayer, Audio, Video
133*/
134
135void QDeclarativePlaylist::_q_mediaAboutToBeInserted(int start, int end)
136{
137 emit itemAboutToBeInserted(start, end);
138
139 beginInsertRows(parent: QModelIndex(), first: start, last: end);
140}
141
142void QDeclarativePlaylist::_q_mediaInserted(int start, int end)
143{
144 endInsertRows();
145
146 emit itemCountChanged();
147 emit itemInserted(start, end);
148}
149
150void QDeclarativePlaylist::_q_mediaAboutToBeRemoved(int start, int end)
151{
152 emit itemAboutToBeRemoved(start, end);
153
154 beginRemoveRows(parent: QModelIndex(), first: start, last: end);
155}
156
157void QDeclarativePlaylist::_q_mediaRemoved(int start, int end)
158{
159 endRemoveRows();
160
161 emit itemCountChanged();
162 emit itemRemoved(start, end);
163}
164
165void QDeclarativePlaylist::_q_mediaChanged(int start, int end)
166{
167 emit dataChanged(topLeft: createIndex(arow: start, acolumn: 0), bottomRight: createIndex(arow: end, acolumn: 0));
168 emit itemChanged(start, end);
169}
170
171void QDeclarativePlaylist::_q_loadFailed()
172{
173 m_error = m_playlist->error();
174 m_errorString = m_playlist->errorString();
175
176 emit error(error: Error(m_error), errorString: m_errorString);
177 emit errorChanged();
178 emit loadFailed();
179}
180
181QDeclarativePlaylist::QDeclarativePlaylist(QObject *parent)
182 : QAbstractListModel(parent)
183 , m_playlist(0)
184 , m_error(QMediaPlaylist::NoError)
185 , m_readOnly(false)
186{
187}
188
189QDeclarativePlaylist::~QDeclarativePlaylist()
190{
191 delete m_playlist;
192}
193
194/*!
195 \qmlproperty enumeration QtMultimedia::Playlist::playbackMode
196
197 This property holds the order in which items in the playlist are played.
198
199 \table
200 \header \li Value \li Description
201 \row \li CurrentItemOnce
202 \li The current item is played only once.
203 \row \li CurrentItemInLoop
204 \li The current item is played repeatedly in a loop.
205 \row \li Sequential
206 \li Playback starts from the current and moves through each successive item until the last
207 is reached and then stops. The next item is a null item when the last one is currently
208 playing.
209 \row \li Loop
210 \li Playback restarts at the first item after the last has finished playing.
211 \row \li Random
212 \li Play items in random order.
213 \endtable
214 */
215QDeclarativePlaylist::PlaybackMode QDeclarativePlaylist::playbackMode() const
216{
217 return PlaybackMode(m_playlist->playbackMode());
218}
219
220void QDeclarativePlaylist::setPlaybackMode(PlaybackMode mode)
221{
222 if (playbackMode() == mode)
223 return;
224
225 m_playlist->setPlaybackMode(QMediaPlaylist::PlaybackMode(mode));
226}
227
228/*!
229 \qmlproperty url QtMultimedia::Playlist::currentItemsource
230
231 This property holds the source URL of the current item in the playlist.
232 */
233QUrl QDeclarativePlaylist::currentItemSource() const
234{
235 return m_playlist->currentMedia().request().url();
236}
237
238/*!
239 \qmlproperty int QtMultimedia::Playlist::currentIndex
240
241 This property holds the position of the current item in the playlist.
242 */
243int QDeclarativePlaylist::currentIndex() const
244{
245 return m_playlist->currentIndex();
246}
247
248void QDeclarativePlaylist::setCurrentIndex(int index)
249{
250 if (currentIndex() == index)
251 return;
252
253 m_playlist->setCurrentIndex(index);
254}
255
256/*!
257 \qmlproperty int QtMultimedia::Playlist::itemCount
258
259 This property holds the number of items in the playlist.
260 */
261int QDeclarativePlaylist::itemCount() const
262{
263 return m_playlist->mediaCount();
264}
265
266/*!
267 \qmlproperty bool QtMultimedia::Playlist::readOnly
268
269 This property indicates if the playlist can be modified.
270 */
271bool QDeclarativePlaylist::readOnly() const
272{
273 // There's no signal to tell whether or not the read only state changed, so we consider it fixed
274 // after its initial retrieval in componentComplete().
275 return m_readOnly;
276}
277
278/*!
279 \qmlproperty enumeration QtMultimedia::Playlist::error
280
281 This property holds the error condition of the playlist.
282
283 \table
284 \header \li Value \li Description
285 \row \li NoError
286 \li No errors
287 \row \li FormatError
288 \li Format error.
289 \row \li FormatNotSupportedError
290 \li Format not supported.
291 \row \li NetworkError
292 \li Network error.
293 \row \li AccessDeniedError
294 \li Access denied error.
295 \endtable
296 */
297QDeclarativePlaylist::Error QDeclarativePlaylist::error() const
298{
299 return Error(m_error);
300}
301
302/*!
303 \qmlproperty string QtMultimedia::Playlist::errorString
304
305 This property holds a string describing the current error condition of the playlist.
306*/
307QString QDeclarativePlaylist::errorString() const
308{
309 return m_errorString;
310}
311
312/*!
313 \qmlmethod url QtMultimedia::Playlist::itemSource(index)
314
315 Returns the source URL of the item at the given \a index in the playlist.
316*/
317QUrl QDeclarativePlaylist::itemSource(int index)
318{
319 return m_playlist->media(index).request().url();
320}
321
322/*!
323 \qmlmethod int QtMultimedia::Playlist::nextIndex(steps)
324
325 Returns the index of the item in the playlist which would be current after calling next()
326 \a steps times.
327
328 Returned value depends on the size of the playlist, the current position and the playback mode.
329
330 \sa playbackMode, previousIndex()
331*/
332int QDeclarativePlaylist::nextIndex(int steps)
333{
334 return m_playlist->nextIndex(steps);
335}
336
337/*!
338 \qmlmethod int QtMultimedia::Playlist::previousIndex(steps)
339
340 Returns the index of the item in the playlist which would be current after calling previous()
341 \a steps times.
342
343 Returned value depends on the size of the playlist, the current position and the playback mode.
344
345 \sa playbackMode, nextIndex()
346*/
347int QDeclarativePlaylist::previousIndex(int steps)
348{
349 return m_playlist->previousIndex(steps);
350}
351
352/*!
353 \qmlmethod QtMultimedia::Playlist::next()
354
355 Advances to the next item in the playlist.
356*/
357void QDeclarativePlaylist::next()
358{
359 m_playlist->next();
360}
361
362/*!
363 \qmlmethod QtMultimedia::Playlist::previous()
364
365 Returns to the previous item in the playlist.
366*/
367void QDeclarativePlaylist::previous()
368{
369 m_playlist->previous();
370}
371
372/*!
373 \qmlmethod QtMultimedia::Playlist::shuffle()
374
375 Shuffles items in the playlist.
376*/
377void QDeclarativePlaylist::shuffle()
378{
379 m_playlist->shuffle();
380}
381
382/*!
383 \qmlmethod QtMultimedia::Playlist::load(location, format)
384
385 Loads a playlist from the given \a location. If \a format is specified, it is used, otherwise
386 the format is guessed from the location name and the data.
387
388 New items are appended to the playlist.
389
390 \c onloaded() is emitted if the playlist loads successfully, otherwise \c onLoadFailed() is
391 emitted with \l error and \l errorString defined accordingly.
392*/
393void QDeclarativePlaylist::load(const QUrl &location, const QString &format)
394{
395 m_error = QMediaPlaylist::NoError;
396 m_errorString = QString();
397 emit errorChanged();
398 m_playlist->load(location, format: format.toLatin1().constData());
399}
400
401/*!
402 \qmlmethod bool QtMultimedia::Playlist::save(location, format)
403
404 Saves the playlist to the given \a location. If \a format is specified, it is used, otherwise
405 the format is guessed from the location name.
406
407 Returns true if the playlist is saved successfully.
408*/
409bool QDeclarativePlaylist::save(const QUrl &location, const QString &format)
410{
411 return m_playlist->save(location, format: format.toLatin1().constData());
412}
413
414/*!
415 \qmlmethod bool QtMultimedia::Playlist::addItem(source)
416
417 Appends the \a source URL to the playlist.
418
419 Returns true if the \a source is added successfully.
420*/
421bool QDeclarativePlaylist::addItem(const QUrl &source)
422{
423 return m_playlist->addMedia(content: QMediaContent(source));
424}
425
426/*!
427 \qmlmethod bool QtMultimedia::Playlist::addItems(sources)
428
429 Appends the list of URLs in \a sources to the playlist.
430
431 Returns true if the \a sources are added successfully.
432
433 \since 5.7
434*/
435bool QDeclarativePlaylist::addItems(const QList<QUrl> &sources)
436{
437 if (sources.isEmpty())
438 return false;
439
440 QList<QMediaContent> contents;
441 QList<QUrl>::const_iterator it = sources.constBegin();
442 while (it != sources.constEnd()) {
443 contents.push_back(t: QMediaContent(*it));
444 ++it;
445 }
446 return m_playlist->addMedia(items: contents);
447}
448
449/*!
450 \qmlmethod bool QtMultimedia::Playlist::insertItem(index, source)
451
452 Inserts the \a source URL to the playlist at the given \a index.
453
454 Returns true if the \a source is added successfully.
455*/
456bool QDeclarativePlaylist::insertItem(int index, const QUrl &source)
457{
458 return m_playlist->insertMedia(index, content: QMediaContent(source));
459}
460
461/*!
462 \qmlmethod bool QtMultimedia::Playlist::insertItems(index, sources)
463
464 Inserts the list of URLs in \a sources to the playlist at the given \a index.
465
466 Returns true if the \a sources are added successfully.
467
468 \since 5.7
469*/
470bool QDeclarativePlaylist::insertItems(int index, const QList<QUrl> &sources)
471{
472 if (sources.empty())
473 return false;
474
475 QList<QMediaContent> contents;
476 QList<QUrl>::const_iterator it = sources.constBegin();
477 while (it != sources.constEnd()) {
478 contents.push_back(t: QMediaContent(*it));
479 ++it;
480 }
481 return m_playlist->insertMedia(index, items: contents);
482}
483
484/*!
485 \qmlmethod bool QtMultimedia::Playlist::moveItem(from, to)
486
487 Moves the item at index position \a from to index position \a to.
488
489 Returns \c true if the item is moved successfully.
490
491 \since 5.7
492*/
493bool QDeclarativePlaylist::moveItem(int from, int to)
494{
495 return m_playlist->moveMedia(from, to);
496}
497
498/*!
499 \qmlmethod bool QtMultimedia::Playlist::removeItem(index)
500
501 Removes the item at the given \a index from the playlist.
502
503 Returns \c true if the item is removed successfully.
504*/
505bool QDeclarativePlaylist::removeItem(int index)
506{
507 return m_playlist->removeMedia(pos: index);
508}
509
510/*!
511 \qmlmethod bool QtMultimedia::Playlist::removeItems(int start, int end)
512
513 Removes items in the playlist from \a start to \a end inclusive.
514
515 Returns \c true if the items are removed successfully.
516
517 \since 5.7
518*/
519bool QDeclarativePlaylist::removeItems(int start, int end)
520{
521 return m_playlist->removeMedia(start, end);
522}
523
524/*!
525 \qmlmethod bool QtMultimedia::Playlist::clear()
526
527 Removes all the items from the playlist.
528
529 Returns \c true if the operation is successful.
530*/
531bool QDeclarativePlaylist::clear()
532{
533 return m_playlist->clear();
534}
535
536int QDeclarativePlaylist::rowCount(const QModelIndex &parent) const
537{
538 if (parent.isValid())
539 return 0;
540
541 return m_playlist->mediaCount();
542}
543
544QVariant QDeclarativePlaylist::data(const QModelIndex &index, int role) const
545{
546 Q_UNUSED(role);
547
548 if (!index.isValid())
549 return QVariant();
550
551 return m_playlist->media(index: index.row()).request().url();
552}
553
554QHash<int, QByteArray> QDeclarativePlaylist::roleNames() const
555{
556 QHash<int, QByteArray> roleNames;
557 roleNames[SourceRole] = "source";
558 return roleNames;
559}
560
561void QDeclarativePlaylist::classBegin()
562{
563 m_playlist = new QMediaPlaylist(this);
564
565 connect(sender: m_playlist, SIGNAL(currentIndexChanged(int)),
566 receiver: this, SIGNAL(currentIndexChanged()));
567 connect(sender: m_playlist, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
568 receiver: this, SIGNAL(playbackModeChanged()));
569 connect(sender: m_playlist, SIGNAL(currentMediaChanged(QMediaContent)),
570 receiver: this, SIGNAL(currentItemSourceChanged()));
571 connect(sender: m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)),
572 receiver: this, SLOT(_q_mediaAboutToBeInserted(int,int)));
573 connect(sender: m_playlist, SIGNAL(mediaInserted(int,int)),
574 receiver: this, SLOT(_q_mediaInserted(int,int)));
575 connect(sender: m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)),
576 receiver: this, SLOT(_q_mediaAboutToBeRemoved(int,int)));
577 connect(sender: m_playlist, SIGNAL(mediaRemoved(int,int)),
578 receiver: this, SLOT(_q_mediaRemoved(int,int)));
579 connect(sender: m_playlist, SIGNAL(mediaChanged(int,int)),
580 receiver: this, SLOT(_q_mediaChanged(int,int)));
581 connect(sender: m_playlist, SIGNAL(loaded()),
582 receiver: this, SIGNAL(loaded()));
583 connect(sender: m_playlist, SIGNAL(loadFailed()),
584 receiver: this, SLOT(_q_loadFailed()));
585
586 if (m_playlist->isReadOnly()) {
587 m_readOnly = true;
588 emit readOnlyChanged();
589 }
590}
591
592void QDeclarativePlaylist::componentComplete()
593{
594}
595
596/*!
597 \qmlsignal QtMultimedia::Playlist::itemAboutToBeInserted(start, end)
598
599 This signal is emitted when items are to be inserted into the playlist at \a start and ending at
600 \a end.
601
602 The corresponding handler is \c onItemAboutToBeInserted.
603*/
604
605/*!
606 \qmlsignal QtMultimedia::Playlist::itemInserted(start, end)
607
608 This signal is emitted after items have been inserted into the playlist. The new items are those
609 between \a start and \a end inclusive.
610
611 The corresponding handler is \c onItemInserted.
612*/
613
614/*!
615 \qmlsignal QtMultimedia::Playlist::itemAboutToBeRemoved(start, end)
616
617 This signal emitted when items are to be deleted from the playlist at \a start and ending at
618 \a end.
619
620 The corresponding handler is \c onItemAboutToBeRemoved.
621*/
622
623/*!
624 \qmlsignal QtMultimedia::Playlist::itemRemoved(start, end)
625
626 This signal is emitted after items have been removed from the playlist. The removed items are
627 those between \a start and \a end inclusive.
628
629 The corresponding handler is \c onMediaRemoved.
630*/
631
632/*!
633 \qmlsignal QtMultimedia::Playlist::itemChanged(start, end)
634
635 This signal is emitted after items have been changed in the playlist between \a start and
636 \a end positions inclusive.
637
638 The corresponding handler is \c onItemChanged.
639*/
640
641/*!
642 \qmlsignal QtMultimedia::Playlist::loaded()
643
644 This signal is emitted when the playlist loading succeeded.
645
646 The corresponding handler is \c onLoaded.
647*/
648
649/*!
650 \qmlsignal QtMultimedia::Playlist::loadFailed()
651
652 This signal is emitted when the playlist loading failed. \l error and \l errorString can be
653 checked for more information on the failure.
654
655 The corresponding handler is \c onLoadFailed.
656*/
657
658QT_END_NAMESPACE
659
660#include "moc_qdeclarativeplaylist_p.cpp"
661

source code of qtmultimedia/src/imports/multimedia/qdeclarativeplaylist.cpp