Merge lp:~renatofilho/mediaplayer-app/video-selector into lp:mediaplayer-app

Proposed by Renato Araujo Oliveira Filho
Status: Needs review
Proposed branch: lp:~renatofilho/mediaplayer-app/video-selector
Merge into: lp:mediaplayer-app
Diff against target: 638 lines (+360/-67)
10 files modified
CMakeLists.txt (+2/-0)
debian/control (+1/-0)
po/mediaplayer-app.pot (+51/-37)
src/CMakeLists.txt (+8/-2)
src/mediaplayer.cpp (+2/-0)
src/qml/VideoSelector.qml (+133/-0)
src/qml/player.qml (+27/-20)
src/qml/player/VideoPlayer.qml (+2/-8)
src/videos-model.cpp (+82/-0)
src/videos-model.h (+52/-0)
To merge this branch: bzr merge lp:~renatofilho/mediaplayer-app/video-selector
Reviewer Review Type Date Requested Status
system-apps-ci-bot continuous-integration Needs Fixing
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+246217@code.launchpad.net

Commit message

Show video selector dialog while opening the app without a video url as argument.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
319. By Renato Araujo Oliveira Filho

Updated pot file.
Updated VideoSelector dialog visual.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

319. By Renato Araujo Oliveira Filho

Updated pot file.
Updated VideoSelector dialog visual.

318. By Renato Araujo Oliveira Filho

Show video selector dialog while opening the app without a video url as argument.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-10-02 13:42:17 +0000
3+++ CMakeLists.txt 2015-01-13 14:10:22 +0000
4@@ -34,12 +34,14 @@
5 find_package(Qt5Quick)
6
7 include(FindPkgConfig)
8+pkg_check_modules(MEDIA_SCANNER REQUIRED mediascanner-2.0)
9 #pkg_check_modules(GSTLIB REQUIRED gstreamer-1.0)
10
11 # Standard install paths
12 include(GNUInstallDirs)
13
14 set(MEDIAPLAYER_DIR ${CMAKE_INSTALL_FULL_DATADIR}/mediaplayer-app)
15+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
16
17 # for dh_translations to extract the domain
18 # (regarding syntax consistency, see http://pad.lv/1181187)
19
20=== modified file 'debian/control'
21--- debian/control 2014-08-19 15:14:01 +0000
22+++ debian/control 2015-01-13 14:10:22 +0000
23@@ -7,6 +7,7 @@
24 dh-translations,
25 libgl1-mesa-dev | libgl-dev,
26 libgles2-mesa-dev,
27+ libmediascanner-2.0-dev,
28 pkg-config,
29 python3,
30 qtbase5-dev,
31
32=== modified file 'po/mediaplayer-app.pot'
33--- po/mediaplayer-app.pot 2014-11-05 22:59:33 +0000
34+++ po/mediaplayer-app.pot 2015-01-13 14:10:22 +0000
35@@ -1,14 +1,14 @@
36 # SOME DESCRIPTIVE TITLE.
37-# Copyright (C) YEAR Canonical Ltd.
38+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
39 # This file is distributed under the same license as the PACKAGE package.
40 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
41 #
42 #, fuzzy
43 msgid ""
44 msgstr ""
45-"Project-Id-Version: mediaplayer-app\n"
46+"Project-Id-Version: PACKAGE VERSION\n"
47 "Report-Msgid-Bugs-To: \n"
48-"POT-Creation-Date: 2014-11-05 14:28-0300\n"
49+"POT-Creation-Date: 2015-01-13 11:09-0300\n"
50 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
51 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
52 "Language-Team: LANGUAGE <LL@li.org>\n"
53@@ -19,82 +19,96 @@
54
55 #. TRANSLATORS: this refers to a duration/remaining time of the video, of which you can change the order.
56 #. %1 refers to hours, %2 refers to minutes and %3 refers to seconds.
57-#: ../src/qml/player/TimeLine.qml:52
58+#: src/qml/player/TimeLine.qml:52
59 #, qt-format
60 msgid "%1:%2:%3"
61 msgstr ""
62
63-#: ../src/qml/player/TimeLine.qml:75
64+#: src/qml/player/TimeLine.qml:75
65 msgid "0:00:00"
66 msgstr ""
67
68-#: ../src/qml/player/VideoPlayer.qml:238
69+#: src/qml/player/VideoPlayer.qml:232
70 msgid "A network error occurred."
71 msgstr ""
72
73-#: ../src/qml/player/VideoPlayer.qml:216
74+#: src/qml/VideoSelector.qml:129
75+msgid "Cancel"
76+msgstr ""
77+
78+#: src/qml/player/VideoPlayer.qml:210
79 msgid "Close"
80 msgstr ""
81
82-#: ../src/qml/player.qml:67
83-msgid "Error"
84+#: src/qml/VideoSelector.qml:113
85+msgid "Duration"
86 msgstr ""
87
88-#: ../src/qml/player/VideoPlayer.qml:212
89+#: src/qml/player/VideoPlayer.qml:206
90 msgid "Error playing video"
91 msgstr ""
92
93-#: ../src/qml/player/VideoPlayer.qml:244
94+#: src/qml/player/VideoPlayer.qml:238
95 msgid "Fail to connect with playback backend."
96 msgstr ""
97
98-#: ../src/qml/player/VideoPlayer.qml:232
99+#: src/qml/player/VideoPlayer.qml:226
100 msgid "Fail to open the source video."
101 msgstr ""
102
103-#: ../data/mediaplayer-app.desktop.in.in.h:1
104-msgid "Media Player"
105-msgstr ""
106-
107-#: ../data/mediaplayer-app.desktop.in.in.h:2
108-msgid "Movies;Movie Player;Video Player"
109-msgstr ""
110-
111-#: ../src/qml/player.qml:68
112-msgid ""
113-"No video selected to play. Connect your phone to your computer to transfer "
114-"videos to the phone. Then select video from Videos scope."
115-msgstr ""
116-
117-#: ../src/qml/player.qml:71
118-msgid "Ok"
119-msgstr ""
120-
121-#: ../src/qml/player.qml:189
122+#: src/qml/player.qml:196
123 msgid "Pause or Resume Playhead"
124 msgstr ""
125
126-#: ../src/qml/player.qml:188
127+#: src/qml/player.qml:195
128 msgid "Play / Pause"
129 msgstr ""
130
131-#: ../src/qml/player.qml:194
132+#: src/qml/player.qml:201
133 msgid "Post;Upload;Attach"
134 msgstr ""
135
136-#: ../src/qml/player.qml:193
137+#: src/qml/VideoSelector.qml:94
138+msgid "Select a video to play"
139+msgstr ""
140+
141+#: src/qml/player.qml:200
142 msgid "Share"
143 msgstr ""
144
145-#: ../src/qml/player/VideoPlayer.qml:241
146+#: src/qml/player/VideoPlayer.qml:235
147 msgid "There are not the appropriate permissions to play a media resource."
148 msgstr ""
149
150-#: ../src/qml/player/VideoPlayer.qml:235
151+#: src/qml/VideoSelector.qml:50
152+msgid "Unknown"
153+msgstr ""
154+
155+#: src/qml/player/VideoPlayer.qml:229
156 msgid "Video format not supported."
157 msgstr ""
158
159+#: src/qml/VideoSelector.qml:63
160+msgid "days"
161+msgstr ""
162+
163+#: src/qml/VideoSelector.qml:66
164+msgid "hours"
165+msgstr ""
166+
167+#: src/qml/VideoSelector.qml:69
168+msgid "minutes"
169+msgstr ""
170+
171+#: src/qml/VideoSelector.qml:72
172+msgid "seconds"
173+msgstr ""
174+
175 #. TRANSLATORS: this refers to an unknown duration.
176-#: ../src/qml/player/TimeLine.qml:72
177+#: src/qml/player/TimeLine.qml:72
178 msgid "unknown"
179 msgstr ""
180+
181+#: src/qml/VideoSelector.qml:60
182+msgid "years"
183+msgstr ""
184
185=== modified file 'src/CMakeLists.txt'
186--- src/CMakeLists.txt 2014-10-09 20:28:57 +0000
187+++ src/CMakeLists.txt 2015-01-13 14:10:22 +0000
188@@ -5,19 +5,24 @@
189 include_directories(
190 ${CMAKE_BINARY_DIR}
191 ${sdkhelper_SOURCE_DIR}
192+ ${MEDIA_SCANNER_INCLUDE_DIRS}
193 #${GSTLIB_INCLUDE_DIRS}
194 )
195
196 set(mediaplayer_HDRS
197 #thumbnail-provider.h
198 #thumbnail-pipeline-gst.h
199- mediaplayer.h)
200+ mediaplayer.h
201+ videos-model.h
202+)
203
204 set(mediaplayer_SRCS
205 #thumbnail-provider.cpp
206 #thumbnail-pipeline-gst.cpp
207 mediaplayer.cpp
208- main.cpp)
209+ main.cpp
210+ videos-model.cpp
211+)
212
213 add_executable(${MEDIAPLAYER}
214 ${mediaplayer_MOC_SRCS}
215@@ -28,6 +33,7 @@
216
217 target_link_libraries(${MEDIAPLAYER}
218 #${GSTLIB_LDFLAGS}
219+ ${MEDIA_SCANNER_LDFLAGS}
220 )
221
222 install(TARGETS ${MEDIAPLAYER}
223
224=== modified file 'src/mediaplayer.cpp'
225--- src/mediaplayer.cpp 2014-08-25 13:53:31 +0000
226+++ src/mediaplayer.cpp 2015-01-13 14:10:22 +0000
227@@ -14,6 +14,7 @@
228 * along with this program. If not, see <http://www.gnu.org/licenses/>.
229 */
230 #include "mediaplayer.h"
231+#include "videos-model.h"
232 //#include "thumbnail-provider.h"
233 //#include "sharefile.h"
234
235@@ -81,6 +82,7 @@
236
237 //TODO: move this to SDK/ShareMenu library
238 //qmlRegisterType<ShareFile>("SDKHelper", 1, 0, "ShareFile");
239+ qmlRegisterType<VideosModel>("MediaPlayerHelper", 1, 0, "VideosModel");
240
241 m_view = new QQuickView();
242 //m_view->engine()->addImageProvider("video", new ThumbnailProvider);
243
244=== added file 'src/qml/VideoSelector.qml'
245--- src/qml/VideoSelector.qml 1970-01-01 00:00:00 +0000
246+++ src/qml/VideoSelector.qml 2015-01-13 14:10:22 +0000
247@@ -0,0 +1,133 @@
248+/*
249+ * Copyright (C) 2013 Canonical, Ltd.
250+ *
251+ * Authors:
252+ * Ugo Riboni <ugo.riboni@canonical.com>
253+ * MichaƂ Sawicz <michal.sawicz@canonical.com>
254+ * Renato Araujo Oliveira Filho <renato@canonical.com>
255+ *
256+ * This program is free software; you can redistribute it and/or modify
257+ * it under the terms of the GNU General Public License as published by
258+ * the Free Software Foundation; version 3.
259+ *
260+ * This program is distributed in the hope that it will be useful,
261+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
262+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
263+ * GNU General Public License for more details.
264+ *
265+ * You should have received a copy of the GNU General Public License
266+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
267+ */
268+
269+import QtQuick 2.0
270+import Ubuntu.Thumbnailer 0.1
271+import Ubuntu.Components 1.1
272+import Ubuntu.Components.Popups 1.0
273+import Ubuntu.Components.ListItems 1.0 as ListItem
274+
275+import MediaPlayerHelper 1.0 as MediaPlayer
276+
277+Item {
278+ id: root
279+
280+ property var currentDialog: null
281+ signal videoSelected(string videoUrl)
282+
283+ function show()
284+ {
285+ videoList.model.reload()
286+ dialog.visible = true
287+ }
288+
289+ function hide()
290+ {
291+ dialog.visible = false
292+ }
293+
294+ function secondsToString(seconds)
295+ {
296+ if (seconds <= 0)
297+ return i18n.tr("Unknown")
298+
299+ var numyears = Math.floor(seconds / 31536000);
300+ var numdays = Math.floor((seconds % 31536000) / 86400);
301+ var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
302+ var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
303+ var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
304+
305+ var result = ""
306+ if (numyears > 0)
307+ result += "%1 %2".arg(numyears).arg(i18n.tr("years"))
308+
309+ if (numdays > 0)
310+ result += " %1 %2".arg(numdays).arg(i18n.tr("days"))
311+
312+ if (numhours > 0)
313+ result += " %1 %2".arg(numhours).arg(i18n.tr("hours"))
314+
315+ if (numminutes > 0)
316+ result += " %1 %2".arg(numminutes).arg(i18n.tr("minutes"))
317+
318+ if (numseconds > 0)
319+ result += " %1 %2".arg(numseconds).arg(i18n.tr("seconds"))
320+
321+ return result.trim()
322+ }
323+
324+ Rectangle {
325+ id: dialog
326+
327+ width: root.width
328+ height: root.height
329+ color: Theme.palette.normal.overlay
330+ visible: false
331+
332+ Header {
333+ id: title
334+
335+ anchors {
336+ left: parent.left
337+ top: parent.top
338+ right: parent.right
339+ }
340+
341+ title: i18n.tr("Select a video to play")
342+ //fontSize: "large"
343+ }
344+
345+ ListView {
346+ id: videoList
347+
348+ anchors {
349+ left: parent.left
350+ top: title.bottom
351+ topMargin: units.gu(1)
352+ right: parent.right
353+ bottom: openButton.top
354+ bottomMargin: units.gu(1)
355+ }
356+ clip: true // because of the title
357+ model: MediaPlayer.VideosModel {}
358+ delegate: ListItem.Subtitled {
359+ text: model.title
360+ subText: "%1: %2".arg(i18n.tr("Duration")).arg(secondsToString(model.duration))
361+ iconSource: model.art
362+ onClicked: root.videoSelected(model.uri)
363+ }
364+ }
365+
366+ Button {
367+ id: openButton
368+
369+ anchors {
370+ left: parent.left
371+ right: parent.right
372+ bottom: parent.bottom
373+ margins: units.gu(1)
374+ }
375+
376+ text: i18n.tr("Cancel")
377+ onClicked: Qt.quit()
378+ }
379+ }
380+}
381
382=== modified file 'src/qml/player.qml'
383--- src/qml/player.qml 2014-10-15 21:26:33 +0000
384+++ src/qml/player.qml 2015-01-13 14:10:22 +0000
385@@ -36,6 +36,7 @@
386 property string formFactor: "phone"
387 property real volume: playerLoader.item.volume
388 property bool appActive: Qt.application.active
389+ property bool emptyVideoUrl: false
390
391 property variant nativeOrientation: Screen.primaryOrientation
392
393@@ -57,24 +58,6 @@
394 i18n.domain = "mediaplayer-app"
395 }
396
397- Component {
398- id: dialogNoUrl
399-
400- Popups.Dialog {
401- id: dialogue
402- objectName: "noMediaDialog"
403-
404- title: i18n.tr("Error")
405- text: i18n.tr("No video selected to play. Connect your phone to your computer to transfer videos to the phone. Then select video from Videos scope.")
406-
407- Button {
408- text: i18n.tr("Ok")
409- gradient: UbuntuColors.greyGradient
410- onClicked: Qt.quit()
411- }
412- }
413- }
414-
415 Loader {
416 id: playerLoader
417
418@@ -85,7 +68,8 @@
419 onLoaded: {
420 item.focus = true
421 item.rotating = Qt.binding(function () { return rotatingTransition.running } )
422- if (playUri != "") {
423+ mediaPlayer.emptyVideoUrl = (playUri == "")
424+ if (!mediaPlayer.emptyVideoUrl) {
425 item.playUri(playUri)
426 } else {
427 if (mpApplication.desktopMode) {
428@@ -94,7 +78,20 @@
429 item.playUri(videoFile)
430 }
431 } else {
432- PopupUtils.open(dialogNoUrl, null)
433+ dialogVideoSelector.show()
434+ }
435+ }
436+ }
437+
438+ Connections {
439+ target: playerLoader.item
440+ onFullScreenClicked: {
441+ if (mpApplication.desktopMode) {
442+ mpApplication.toggleFullscreen()
443+ } else if (mediaPlayer.emptyVideoUrl) {
444+ dialogVideoSelector.show()
445+ } else {
446+ Qt.quit()
447 }
448 }
449 }
450@@ -172,6 +169,16 @@
451 ]
452 }
453
454+ VideoSelector {
455+ id: dialogVideoSelector
456+
457+ anchors.fill: parent
458+ onVideoSelected: {
459+ hide()
460+ playerLoader.item.playUri(videoUrl)
461+ }
462+ }
463+
464 Connections {
465 target: playerLoader.item
466 onStatusChanged: {
467
468=== modified file 'src/qml/player/VideoPlayer.qml'
469--- src/qml/player/VideoPlayer.qml 2014-10-02 19:11:34 +0000
470+++ src/qml/player/VideoPlayer.qml 2015-01-13 14:10:22 +0000
471@@ -40,6 +40,7 @@
472 property var errorDialog: null
473
474 signal timeClicked
475+ signal fullScreenClicked
476
477 objectName: "player"
478 nfo: VideoInfo {
479@@ -111,14 +112,7 @@
480 sceneSelectorHeight: units.gu(18)
481
482 onPlaybackClicked: player.playPause()
483-
484- onFullscreenClicked: {
485- if (mpApplication.desktopMode) {
486- mpApplication.toggleFullscreen()
487- } else {
488- Qt.quit()
489- }
490- }
491+ onFullscreenClicked: player.fullScreenClicked()
492
493 onSeekRequested: {
494 player.video.seek(time)
495
496=== added file 'src/videos-model.cpp'
497--- src/videos-model.cpp 1970-01-01 00:00:00 +0000
498+++ src/videos-model.cpp 2015-01-13 14:10:22 +0000
499@@ -0,0 +1,82 @@
500+/*
501+ * Copyright (C) 2015 Canonical, Ltd.
502+ *
503+ * This program is free software; you can redistribute it and/or modify
504+ * it under the terms of the GNU General Public License as published by
505+ * the Free Software Foundation; version 3.
506+ *
507+ * This program is distributed in the hope that it will be useful,
508+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
509+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
510+ * GNU General Public License for more details.
511+ *
512+ * You should have received a copy of the GNU General Public License
513+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
514+ */
515+
516+#include "videos-model.h"
517+
518+#include <QHash>
519+
520+#include <mediascanner/Filter.hh>
521+
522+VideosModel::VideosModel(QObject *parent)
523+ : QAbstractListModel(parent),
524+ m_store(new mediascanner::MediaStore(mediascanner::MS_READ_ONLY))
525+{
526+}
527+
528+QHash<int, QByteArray> VideosModel::roleNames() const
529+{
530+ static QHash<int, QByteArray> roles;
531+ if (roles.isEmpty()) {
532+ roles.insert(0, "uri");
533+ roles.insert(1, "art");
534+ roles.insert(2, "title");
535+ roles.insert(3, "duration");
536+ }
537+ return roles;
538+}
539+
540+QVariant VideosModel::data(const QModelIndex &index, int role) const
541+{
542+ if ((index.row() < 0) || (index.row() >= m_files.count())) {
543+ return QVariant();
544+ }
545+
546+ const mediascanner::MediaFile &media = m_files.at(index.row());
547+ switch (role) {
548+ case 0:
549+ return QVariant(QString::fromStdString(media.getUri()));
550+ case 1:
551+ return QVariant(QString::fromStdString(media.getArtUri()));
552+ case 2:
553+ return QVariant(QString::fromStdString(media.getTitle()));
554+ case 3:
555+ return QVariant(media.getDuration());
556+ default:
557+ return QVariant();
558+ }
559+}
560+
561+void VideosModel::reload()
562+{
563+ mediascanner::Filter filter;
564+
565+ beginResetModel();
566+ m_files.clear();
567+
568+ Q_FOREACH(const mediascanner::MediaFile &media,
569+ m_store->query("", mediascanner::VideoMedia, filter)) {
570+
571+ m_files.append(media);
572+ }
573+
574+ endResetModel();
575+ Q_EMIT countChanged();
576+}
577+
578+int VideosModel::rowCount(const QModelIndex &parent) const
579+{
580+ return m_files.count();
581+}
582
583=== added file 'src/videos-model.h'
584--- src/videos-model.h 1970-01-01 00:00:00 +0000
585+++ src/videos-model.h 2015-01-13 14:10:22 +0000
586@@ -0,0 +1,52 @@
587+/*
588+ * Copyright (C) 2015 Canonical, Ltd.
589+ *
590+ * This program is free software; you can redistribute it and/or modify
591+ * it under the terms of the GNU General Public License as published by
592+ * the Free Software Foundation; version 3.
593+ *
594+ * This program is distributed in the hope that it will be useful,
595+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
596+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
597+ * GNU General Public License for more details.
598+ *
599+ * You should have received a copy of the GNU General Public License
600+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
601+ */
602+
603+#ifndef __VIDEOS_MODEL_H__
604+#define __VIDEOS_MODEL_H__
605+
606+#include <QAbstractListModel>
607+#include <QString>
608+#include <QVariant>
609+#include <QScopedPointer>
610+
611+#include <mediascanner/MediaStore.hh>
612+#include <mediascanner/MediaFile.hh>
613+
614+class VideosModel : public QAbstractListModel
615+{
616+ Q_OBJECT
617+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
618+
619+public:
620+ VideosModel(QObject *parent = 0);
621+
622+ QVariant data(const QModelIndex &index, int role) const override;
623+ Q_INVOKABLE void reload();
624+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
625+
626+Q_SIGNALS:
627+ void countChanged();
628+
629+protected:
630+ QHash<int, QByteArray> roleNames() const override;
631+
632+private:
633+ QScopedPointer<mediascanner::MediaStore> m_store;
634+ QList<mediascanner::MediaFile> m_files;
635+};
636+
637+
638+#endif

Subscribers

People subscribed via source and target branches