Merge lp:~mzanetti/unity8/music-preview into lp:unity8

Proposed by Michael Zanetti
Status: Merged
Approved by: Michał Sawicz
Approved revision: 523
Merged at revision: 558
Proposed branch: lp:~mzanetti/unity8/music-preview
Merge into: lp:unity8
Prerequisite: lp:~unity-team/unity8/switching-previews
Diff against target: 784 lines (+661/-0)
15 files modified
Dash/DashPreview.qml (+1/-0)
Dash/GenericScopeView.qml (+1/-0)
Dash/Music/MusicPreview.qml (+203/-0)
Dash/PreviewDelegateMapper.qml (+1/-0)
debian/control (+1/-0)
tests/mocks/CMakeLists.txt (+1/-0)
tests/mocks/QtMultimedia/CMakeLists.txt (+19/-0)
tests/mocks/QtMultimedia/audio.cpp (+107/-0)
tests/mocks/QtMultimedia/audio.h (+78/-0)
tests/mocks/QtMultimedia/plugin.cpp (+28/-0)
tests/mocks/QtMultimedia/plugin.h (+34/-0)
tests/mocks/QtMultimedia/qmldir (+2/-0)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Dash/Music/tst_MusicPreview.qml (+174/-0)
tests/qmltests/Dash/tst_GenericScopeView.qml (+10/-0)
To merge this branch: bzr merge lp:~mzanetti/unity8/music-preview
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michał Sawicz Approve
Michal Hruby (community) Needs Fixing
Review via email: mp+193803@code.launchpad.net

Commit message

Added music preview

To post a comment you must log in.
Revision history for this message
Michal Hruby (mhr3) wrote :

Looking good overall, visually there's one separator missing between the orange button and the tracks, other than that I was able to to get lots of:

Error: "GStreamer encountered a general stream error."

...if I swiped slowly between two albums and returned to the first after revealing the second. Then playing tracks no longer worked, and the one that was playing didn't stop when closing the preview nor when swiping to different previews.

168 + onPositionChanged: print("got percent", percent, position, duration)

Remove pls...

233 +MusicPreviewTrackModel *MusicPreview::tracks() const

MusicPreviewTrackModel* pls, looks wrong this way. :P

And as last thing, some ui tests would be nice? :)

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Looking good overall, visually there's one separator missing between the
> orange button and the tracks, other than that I was able to to get lots of:
>
> Error: "GStreamer encountered a general stream error."
>
> ...if I swiped slowly between two albums and returned to the first after
> revealing the second. Then playing tracks no longer worked, and the one that
> was playing didn't stop when closing the preview nor when swiping to different
> previews.
>
> 168 + onPositionChanged: print("got percent",
> percent, position, duration)
>
> Remove pls...
>
> 233 +MusicPreviewTrackModel *MusicPreview::tracks() const
>
> MusicPreviewTrackModel* pls, looks wrong this way. :P
>
> And as last thing, some ui tests would be nice? :)

Yes. tests are coming, that's why it is WIP still. Will fix rest of the stuff when I'm back next week.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Looking good overall, visually there's one separator missing between the
> orange button and the tracks,

fixed.

> other than that I was able to to get lots of:
>
> Error: "GStreamer encountered a general stream error."
>
> ...if I swiped slowly between two albums and returned to the first after
> revealing the second. Then playing tracks no longer worked, and the one that
> was playing didn't stop when closing the preview nor when swiping to different
> previews.

This should be fixed. Switching to another preview stops the playback on the current one. I still see the GStreamer warning every once in a while, but it doesn't seem to break anything.

>
> 168 + onPositionChanged: print("got percent",
> percent, position, duration)
>
> Remove pls...

removed.

>
> 233 +MusicPreviewTrackModel *MusicPreview::tracks() const
>
> MusicPreviewTrackModel* pls, looks wrong this way. :P

fixed.

>
> And as last thing, some ui tests would be nice? :)

added.

Revision history for this message
Michał Sawicz (saviq) wrote :

Hmmm this is playing music in-process in the shell... I'm ok-ish with that if we make sure that's a temporary thing. We should make sure to use the media service when it's available.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Hmmm this is playing music in-process in the shell... I'm ok-ish with that if
> we make sure that's a temporary thing. We should make sure to use the media
> service when it's available.

IMO the Audio {} element should use the media player service implicitly. Otherwise we would have to forbid people to use the Audio element at all and provide our own one instead. Something I strongly object to.

Revision history for this message
Michal Hruby (mhr3) wrote :

> > Error: "GStreamer encountered a general stream error."
> >
> > ...if I swiped slowly between two albums and returned to the first after
> > revealing the second. Then playing tracks no longer worked, and the one that
> > was playing didn't stop when closing the preview nor when swiping to
> different
> > previews.
>
> This should be fixed. Switching to another preview stops the playback on the
> current one. I still see the GStreamer warning every once in a while, but it
> doesn't seem to break anything.

I still see those errors and after a while playback stops working, but it doesn't break as soon as you start seeing them. Just keep swiping back and forth as described.

Revision history for this message
Michał Sawicz (saviq) wrote :

On 12.11.2013 14:26, Michael Zanetti wrote:
> IMO the Audio {} element should use the media player service implicitly. Otherwise we would have to forbid people to use the Audio element at all and provide our own one instead. Something I strongly object to.

Right. Result will be the same (we'll be using the system-wide
media-player), even if this code will not change at all ;).

I'm game with that, then.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> I still see those errors and after a while playback stops working, but it
> doesn't break as soon as you start seeing them. Just keep swiping back and
> forth as described.

After debugging this for a while this seems to be a race condition somewhere in the deeper layers. It happens when there are too many Audio elements instantiated and deleted simultaneously. I changed the code to only use one Audio element per preview which is a better idea in any case. Should also prevent pulseaudio from locking up.

Revision history for this message
Michał Sawicz (saviq) wrote :

Missing Dash/Music/graphics/music_progress_bg.png ?

review: Needs Information
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Missing Dash/Music/graphics/music_progress_bg.png ?

fixed

Revision history for this message
Michał Sawicz (saviq) wrote :

8 + property bool isCurrent: false

20 + Binding {
21 + target: item
22 + property: "isCurrent"
23 + value: previewListView.currentIndex == index
24 + }
25 +

102 + Connections {
103 + target: root
104 + onIsCurrentChanged: {
105 + if (!root.isCurrent) {
106 + audioPlayer.stop();
107 + }
108 + }
109 + }

ListView.isCurrentItem not working?

=====

99 + onErrorStringChanged: print("Audio player error:", errorString)

Use console.warn() please, so that we can shut this up when we implement a log printer.

=====

101 + }
102 + Connections {

176 + }
177 + MouseArea {

Newline please. There's a few other places, too.

====

112 + anchors {
113 + left: parent.left
114 + right: parent.right
115 + }

121 + anchors {
122 + left: parent.left
123 + right: parent.right
124 + }

Compress to one line?

=====

117 + height: childrenRect.height

That's the default for a Column.

=====

125 + visible: trackRepeater.count > 0

Shouldn't the whole Column be made invisible?

====

139 + property bool isPlayingItem: false

143 + onSourceChanged: trackItem.isPlayingItem = false;

151 + isPlayingItem = true;

I'd be worried this might get out of sync... I know here it's pretty reliable, but just consider this: I usually add a "property Item playingItem" to the Repeater/*View, and then do "isPlayingItem: repeater.playingItem == thisItem", what do you think?

=====

157 + width: parent.width

162 + anchors.verticalCenter: parent.verticalCenter

Use anchors for width, too, please?

=====

164 + UbuntuShape {
165 + id: playButtonShape

Why not Button/AbstractButton? There's no touchdown effect on tap.

=====

159 + property int column1Width: units.gu(3)
160 + property int column2Width: width - (2 * spacing) - column1Width - column3Width
161 + property int column3Width: units.gu(4)

Eek... /me wants Qt 5.2's layouts ;)

=====

206 + UbuntuShape {
207 + id: progressBarFill

No way to use the SDK's progress bar that small? Please chat with them whether they'd want it there.

=====

223 + top: parent.bottom

I'm always frowning at items outside of their parents...

=====

229 +

Bad newline.

=====

We sure QtMultimedia will work in all our testing environments? Should we maybe think of a mock QtMultimedia backend?

=====

Missing Depends on qtmultimedia.

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> ListView.isCurrentItem not working?

fixed.
>
> =====
>
> 99 + onErrorStringChanged: print("Audio player error:", errorString)
>
> Use console.warn() please, so that we can shut this up when we implement a log
> printer.

fixed.

>
> =====
> Newline please. There's a few other places, too.

fixed.

>
> ====
>
> Compress to one line?

fixed

>
> =====
>
> 117 + height: childrenRect.height
>
> That's the default for a Column.

I don't trust it :D ... removed.

>
> =====
>
> 125 + visible: trackRepeater.count > 0
>
> Shouldn't the whole Column be made invisible?

Doesn't really make a difference I'd say. but sure. might spare us some very few cpu cycles indeed. moved

>
> ====
>
> 139 + property bool isPlayingItem: false
>
> 143 + onSourceChanged: trackItem.isPlayingItem = false;
>
> 151 + isPlayingItem = true;
>
> I'd be worried this might get out of sync... I know here it's pretty reliable,
> but just consider this: I usually add a "property Item playingItem" to the
> Repeater/*View, and then do "isPlayingItem: repeater.playingItem == thisItem",
> what do you think?

Good point, yes. fixed.

>
> =====
>
> Use anchors for width, too, please?

fixed.

>
> =====
>
> 164 + UbuntuShape {
> 165 + id: playButtonShape
>
> Why not Button/AbstractButton? There's no touchdown effect on tap.

hmm... at least so far it only plays when clicking the play button. Need to check with design. But isn't the touchdown effect exactly what we did *not* want to have according to some bug for the people lens?

>
> =====
>
> 159 + property int column1Width: units.gu(3)
> 160 + property int column2Width: width - (2 * spacing) - column1Width -
> column3Width
> 161 + property int column3Width: units.gu(4)
>
> Eek... /me wants Qt 5.2's layouts ;)

+1 :)

>
> ========
>
> 223 + top: parent.bottom
>
> I'm always frowning at items outside of their parents...

I agree it's usually bad practice. In this small case however it greatly simplifies layouting as the text should still be vCentered and the progress bar attached to it. Also no contained items or clipping items around. Ok with exception?

>
> =====
>
> 229 +
>
> Bad newline.

fixed

>
>
> Missing Depends on qtmultimedia.

fixed.

*****************

Still to clarify:

> =====
>
> We sure QtMultimedia will work in all our testing environments? Should we
> maybe think of a mock QtMultimedia backend?
>
> =====
>
> 206 + UbuntuShape {
> 207 + id: progressBarFill
>
> No way to use the SDK's progress bar that small? Please chat with them whether
> they'd want it there.
>
> =====

Revision history for this message
Michael Zanetti (mzanetti) wrote :

>
> 206 + UbuntuShape {
> 207 + id: progressBarFill
>
> No way to use the SDK's progress bar that small? Please chat with them whether
> they'd want it there.

Evaluated this again and had a chat with SDK: Cannot use the SDK's progress bar as it doesn't really fit design wise and implementation wise. Given that this will need to have the cached percentage indication too at some point (when scopes backend supports it) SDK guys think this is too specific to Music players to be included in the SDK.

> ====
>
> We sure QtMultimedia will work in all our testing environments? Should we
> maybe think of a mock QtMultimedia backend?
>

mocked.

Revision history for this message
Michał Sawicz (saviq) wrote :

On 13.11.2013 20:12, Michael Zanetti wrote:

> hmm... at least so far it only plays when clicking the play button. Need to check with design. But isn't the touchdown effect exactly what we did *not* want to have according to some bug for the people lens?

I meant why don't you use AbstractButton/Button on the play button
itself - not for the whole delegate. Also, we didn't want a touchdown
effect kick in too soon when swiping, we want it when you actually
press. Sure, this button is smallish, so not visible with a finger, but
it will be visible with a mouse, so let's add it.

>> I'm always frowning at items outside of their parents...
>
> I agree it's usually bad practice. In this small case however it greatly simplifies layouting as the text should still be vCentered and the progress bar attached to it. Also no contained items or clipping items around. Ok with exception?

Yeah, OK.

> Evaluated this again and had a chat with SDK: Cannot use the SDK's progress bar as it doesn't really fit design wise and implementation wise. Given that this will need to have the cached percentage indication too at some point (when scopes backend supports it) SDK guys think this is too specific to Music players to be included in the SDK.

OK.

>> We sure QtMultimedia will work in all our testing environments? Should we
>> maybe think of a mock QtMultimedia backend?
>
> mocked.

Awesome.

--
Michał (Saviq) Sawicz <email address hidden>
Canonical Services Ltd.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> On 13.11.2013 20:12, Michael Zanetti wrote:
>
> > hmm... at least so far it only plays when clicking the play button. Need to
> check with design. But isn't the touchdown effect exactly what we did *not*
> want to have according to some bug for the people lens?
>
> I meant why don't you use AbstractButton/Button on the play button
> itself - not for the whole delegate. Also, we didn't want a touchdown
> effect kick in too soon when swiping, we want it when you actually
> press. Sure, this button is smallish, so not visible with a finger, but
> it will be visible with a mouse, so let's add it.

Hmpf. Didn't work out as well as expected: The normal button is orange which is not what we want here. The AbstractButton instead doesn't have the touch down effect neither and still requires me to use the UbuntuShape as it doesn't render the icon (even though there is an iconSource property). Still I made it an AbstractButton so we'll get updates on the behaviour too.

On another note, I reverted rev 505 as in this case ListView.isCurrentItem doesn't work indeed. Attached properties only work in the top level of the delegate which is a Loader in our case. As I need to bind it to the Loader's item it would even require an intermediate property to consume it in the Binding.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Text conflict in plugins/Unity/plugin.cpp

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Text conflict in plugins/Unity/plugin.cpp

merged

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:519
http://jenkins.qa.ubuntu.com/job/unity8-ci/1689/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/944
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/928
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/347
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/212
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/213
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/213/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/212
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/848
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/944
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/944/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/928
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/928/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3523
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1622

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1689/rebuild

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

PASSED: Continuous integration, rev:519
http://jenkins.qa.ubuntu.com/job/unity8-ci/1710/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/998
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/982
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/380
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/233
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/234
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/234/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/233
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/894
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/998
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/998/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/982
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/982/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3572
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1677

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1710/rebuild

review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

It's not looking great on tablet, think we could improve it quickly?

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:520
http://jenkins.qa.ubuntu.com/job/unity8-ci/1716/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1019
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1003
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/386
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/239
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/240
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/240/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/239
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/914
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1019
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1019/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1003
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1003/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3593
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1699

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1716/rebuild

review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> It's not looking great on tablet, think we could improve it quickly?

Hmm... good question. I guess the only thing would be to move the tracks list over to the ratings&comments section. However, that wouldn't match with design. But otoh I'm not sure we'll ever get ratings&comments for local music.

Revision history for this message
Michał Sawicz (saviq) wrote :

OK well, we'll revisit later.

/me likes!

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

PASSED: Continuous integration, rev:521
http://jenkins.qa.ubuntu.com/job/unity8-ci/1731/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1078
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1061
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/407
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/254
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/255
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/255/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/254
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/963
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1078
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1078/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1061
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1061/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3643
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1752

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1731/rebuild

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:522
http://jenkins.qa.ubuntu.com/job/unity8-ci/1733/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1082/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1065
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/409
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/256
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/257
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/257/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/256
    FAILURE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/964/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1082
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1082/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1065
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1065/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3645
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1754

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1733/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Yup.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:523
http://jenkins.qa.ubuntu.com/job/unity8-ci/1751/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1176/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1159/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/438/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/274
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/275
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/275/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/274
    ABORTED: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1045/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1176
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1176/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1159
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1159/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3720/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1832

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1751/rebuild

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

FAILED: Autolanding.
More details in the following jenkins job:
http://jenkins.qa.ubuntu.com/job/unity8-autolanding/777/
Executed test runs:
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/generic-cleanup-mbs/3440
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1180/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1163/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/439
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-autolanding/163
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-autolanding/163
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-autolanding/163/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-autolanding/163
    ABORTED: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1051/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1180
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1180/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1163
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1163/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3724/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1836

review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Aborted due to bug #1255578.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
http://jenkins.qa.ubuntu.com/job/unity8-autolanding/785/
Executed test runs:
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/generic-cleanup-mbs/3452
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1274/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1248
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/476
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-autolanding/171
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-autolanding/171
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-autolanding/171/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-autolanding/171
    FAILURE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1131/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1274
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1274/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1248
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1248/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3797
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1917

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Dash/DashPreview.qml'
2--- Dash/DashPreview.qml 2013-10-21 11:51:14 +0000
3+++ Dash/DashPreview.qml 2013-11-27 11:27:38 +0000
4@@ -25,6 +25,7 @@
5 property alias showProcessingAction: waitingForActionMouseArea.enabled
6
7 property real previewWidthRatio: 0.5
8+ property bool isCurrent: false
9
10 property Component previewImages
11 property Component header
12
13=== modified file 'Dash/GenericScopeView.qml'
14--- Dash/GenericScopeView.qml 2013-11-19 14:33:40 +0000
15+++ Dash/GenericScopeView.qml 2013-11-27 11:27:38 +0000
16@@ -527,6 +527,7 @@
17 onLoaded: {
18 if (previewListView.onScreen && previewData !== undefined) {
19 item.previewData = Qt.binding(function() { return previewData })
20+ item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
21 }
22 }
23
24
25=== added file 'Dash/Music/MusicPreview.qml'
26--- Dash/Music/MusicPreview.qml 1970-01-01 00:00:00 +0000
27+++ Dash/Music/MusicPreview.qml 2013-11-27 11:27:38 +0000
28@@ -0,0 +1,203 @@
29+/*
30+ * Copyright (C) 2013 Canonical, Ltd.
31+ *
32+ * This program is free software; you can redistribute it and/or modify
33+ * it under the terms of the GNU General Public License as published by
34+ * the Free Software Foundation; version 3.
35+ *
36+ * This program is distributed in the hope that it will be useful,
37+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39+ * GNU General Public License for more details.
40+ *
41+ * You should have received a copy of the GNU General Public License
42+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
43+ */
44+
45+import QtQuick 2.0
46+import QtMultimedia 5.0
47+import Ubuntu.Components 0.1
48+import Ubuntu.Components.ListItems 0.1
49+import ".."
50+import "../Generic"
51+import "../../Components"
52+import "../Previews"
53+
54+GenericPreview {
55+ id: root
56+
57+ previewImages: previewImageComponent
58+ header: headerComponent
59+ description: descriptionComponent
60+
61+ Component {
62+ id: previewImageComponent
63+ LazyImage {
64+ height: units.gu(22)
65+ scaleTo: "height"
66+ source: previewData ? previewData.image : ""
67+ initialHeight: height
68+ initialWidth: height
69+ }
70+ }
71+
72+ Component {
73+ id: headerComponent
74+ Header {
75+ title: previewData.title
76+ subtitle: previewData.subtitle
77+ }
78+ }
79+
80+ Component {
81+ id: descriptionComponent
82+
83+ Item {
84+ height: childrenRect.height
85+ Audio {
86+ id: audioPlayer
87+ objectName: "audioPlayer"
88+ property real progress: audioPlayer.position / audioPlayer.duration
89+
90+ property Item playingItem
91+
92+ Component.onDestruction: {
93+ audioPlayer.stop();
94+ }
95+
96+ onErrorStringChanged: console.warn("Audio player error:", errorString)
97+
98+ }
99+
100+ Connections {
101+ target: root
102+ onIsCurrentChanged: {
103+ if (!root.isCurrent) {
104+ audioPlayer.stop();
105+ }
106+ }
107+ }
108+
109+ Column {
110+ anchors { left: parent.left; right: parent.right }
111+ visible: trackRepeater.count > 0
112+
113+ ThinDivider {
114+ objectName: "topDivider"
115+ anchors { left: parent.left; right: parent.right }
116+ }
117+
118+ Repeater {
119+ id: trackRepeater
120+ objectName: "trackRepeater"
121+
122+ model: previewData.tracks
123+
124+ delegate: Item {
125+ id: trackItem
126+ objectName: "trackItem" + index
127+ anchors { left: parent.left; right: parent.right }
128+ height: units.gu(5)
129+ property bool isPlayingItem: audioPlayer.playingItem == trackItem
130+
131+ function play() {
132+ audioPlayer.stop();
133+ // Make sure we change the source, even if two items point to the same uri location
134+ audioPlayer.source = "";
135+ audioPlayer.source = model.uri;
136+ audioPlayer.playingItem = trackItem;
137+ audioPlayer.play();
138+ }
139+
140+ Row {
141+ id: trackRow
142+ width: parent.width
143+ spacing: units.gu(1)
144+ property int column1Width: units.gu(3)
145+ property int column2Width: width - (2 * spacing) - column1Width - column3Width
146+ property int column3Width: units.gu(4)
147+ anchors.verticalCenter: parent.verticalCenter
148+
149+ Button {
150+ objectName: "playButton"
151+ width: trackRow.column1Width
152+ height: width
153+ iconSource: audioPlayer.playbackState == Audio.PlayingState && trackItem.isPlayingItem ? "image://theme/media-playback-pause" : "image://theme/media-playback-start"
154+
155+ // Can't be "transparent" or "#00xxxxxx" as the button optimizes away the surrounding shape
156+ // FIXME when this is resolved: https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1251685
157+ color: "#01000000"
158+
159+ onClicked: {
160+ if (trackItem.isPlayingItem) {
161+ if (audioPlayer.playbackState == Audio.PlayingState) {
162+ audioPlayer.pause();
163+ } else if (audioPlayer.playbackState == Audio.PausedState){
164+ audioPlayer.play();
165+ }
166+ } else {
167+ trackItem.play();
168+ }
169+ }
170+ }
171+
172+ Label {
173+ objectName: "trackTitleLabel"
174+ fontSize: "small"
175+ opacity: 0.9
176+ color: "white"
177+ horizontalAlignment: Text.AlignLeft
178+ anchors.verticalCenter: parent.verticalCenter
179+ width: parent.column2Width
180+ text: title
181+ style: Text.Raised
182+ styleColor: "black"
183+ elide: Text.ElideRight
184+
185+ UbuntuShape {
186+ id: progressBarFill
187+ objectName: "progressBarFill"
188+ color: UbuntuColors.orange
189+ anchors.left: progressBarImage.left
190+ anchors.right: progressBarImage.right
191+ anchors.verticalCenter: progressBarImage.verticalCenter
192+ height: units.dp(2)
193+ anchors.margins: units.dp(2)
194+ anchors.rightMargin: maxWidth - (maxWidth * audioPlayer.progress) + units.dp(2)
195+ visible: progressBarImage.visible
196+ property int maxWidth: progressBarImage.width - units.dp(4)
197+ }
198+
199+ Image {
200+ id: progressBarImage
201+ anchors { left: parent.left; top: parent.bottom; right: parent.right }
202+ height: units.dp(6)
203+ visible: audioPlayer.playbackState != Audio.StoppedState && trackItem.isPlayingItem && model.length.length > 0
204+ source: "graphics/music_progress_bg.png"
205+ }
206+ }
207+
208+ Label {
209+ id: valueLabel
210+ objectName: "timeLabel"
211+ fontSize: "small"
212+ opacity: 0.9
213+ color: "white"
214+ anchors.verticalCenter: parent.verticalCenter
215+ horizontalAlignment: Text.AlignRight
216+ width: parent.column3Width
217+ text: length
218+ style: Text.Raised
219+ styleColor: "black"
220+ }
221+ }
222+
223+ ThinDivider {
224+ anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
225+ }
226+ }
227+ }
228+ }
229+ }
230+ }
231+}
232
233=== added directory 'Dash/Music/graphics'
234=== added file 'Dash/Music/graphics/music_progress_bg.png'
235Binary files Dash/Music/graphics/music_progress_bg.png 1970-01-01 00:00:00 +0000 and Dash/Music/graphics/music_progress_bg.png 2013-11-27 11:27:38 +0000 differ
236=== modified file 'Dash/PreviewDelegateMapper.qml'
237--- Dash/PreviewDelegateMapper.qml 2013-10-31 15:22:22 +0000
238+++ Dash/PreviewDelegateMapper.qml 2013-11-27 11:27:38 +0000
239@@ -23,6 +23,7 @@
240 property var previewDelegateMapping: {"preview-generic": genericPreview,
241 "preview-application": appPreview,
242 "preview-movie": "Movie/MoviePreview.qml",
243+ "preview-music": "Music/MusicPreview.qml",
244 }
245 }
246
247
248=== modified file 'debian/control'
249--- debian/control 2013-11-25 22:21:23 +0000
250+++ debian/control 2013-11-27 11:27:38 +0000
251@@ -34,6 +34,7 @@
252 qtbase5-private-dev,
253 qtdeclarative5-dev,
254 qtdeclarative5-dev-tools,
255+ qtdeclarative5-qtmultimedia-plugin,
256 qtdeclarative5-private-dev,
257 qtdeclarative5-qtquick2-plugin,
258 qtdeclarative5-test-plugin,
259
260=== modified file 'tests/mocks/CMakeLists.txt'
261--- tests/mocks/CMakeLists.txt 2013-10-16 14:23:03 +0000
262+++ tests/mocks/CMakeLists.txt 2013-11-27 11:27:38 +0000
263@@ -7,6 +7,7 @@
264 add_subdirectory(QMenuModel)
265 add_subdirectory(Ubuntu)
266 add_subdirectory(Unity)
267+add_subdirectory(QtMultimedia)
268
269 install(
270 DIRECTORY data
271
272=== added directory 'tests/mocks/QtMultimedia'
273=== added file 'tests/mocks/QtMultimedia/CMakeLists.txt'
274--- tests/mocks/QtMultimedia/CMakeLists.txt 1970-01-01 00:00:00 +0000
275+++ tests/mocks/QtMultimedia/CMakeLists.txt 2013-11-27 11:27:38 +0000
276@@ -0,0 +1,19 @@
277+add_library(QtMultimedia-qml MODULE
278+ plugin.cpp
279+ audio.cpp
280+ )
281+
282+qt5_use_modules(QtMultimedia-qml Qml)
283+
284+# copy qmldir file into build directory for shadow builds
285+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
286+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
287+ )
288+
289+install(TARGETS QtMultimedia-qml
290+ DESTINATION ${SHELL_INSTALL_QML}/mocks/QtMultimedia
291+ )
292+
293+install(FILES qmldir
294+ DESTINATION ${SHELL_INSTALL_QML}/mocks/QtMultimedia
295+ )
296
297=== added file 'tests/mocks/QtMultimedia/audio.cpp'
298--- tests/mocks/QtMultimedia/audio.cpp 1970-01-01 00:00:00 +0000
299+++ tests/mocks/QtMultimedia/audio.cpp 2013-11-27 11:27:38 +0000
300@@ -0,0 +1,107 @@
301+/*
302+ * Copyright (C) 2013 Canonical, Ltd.
303+ *
304+ * This program is free software; you can redistribute it and/or modify
305+ * it under the terms of the GNU General Public License as published by
306+ * the Free Software Foundation; version 3.
307+ *
308+ * This program is distributed in the hope that it will be useful,
309+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
310+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
311+ * GNU General Public License for more details.
312+ *
313+ * You should have received a copy of the GNU General Public License
314+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
315+ *
316+ * Author: Michael Zanetti <michael.zanetti@canonical.com>
317+ */
318+
319+#include "audio.h"
320+
321+Audio::Audio(QObject* parent):
322+ QObject(parent),
323+ m_playbackState(StoppedState)
324+{
325+ qsrand(time(NULL));
326+ m_timer.setInterval(1000);
327+ connect(&m_timer, SIGNAL(timeout()), SLOT(timerEvent()));
328+}
329+
330+QUrl Audio::source() const
331+{
332+ return m_source;
333+}
334+
335+void Audio::setSource(const QUrl &source)
336+{
337+ if (m_source != source) {
338+ m_source = source;
339+ Q_EMIT sourceChanged(source);
340+
341+ m_position = 0;
342+ Q_EMIT positionChanged(m_position);
343+
344+ m_duration = (qrand() % 20000) + 10000;
345+ Q_EMIT durationChanged(m_duration);
346+ }
347+}
348+
349+Audio::PlaybackState Audio::playbackState() const
350+{
351+ return m_playbackState;
352+}
353+
354+int Audio::position() const
355+{
356+ return m_position;
357+}
358+
359+int Audio::duration() const
360+{
361+ return m_duration;
362+}
363+
364+QString Audio::errorString() const
365+{
366+ return QString();
367+}
368+
369+void Audio::pause()
370+{
371+ if (m_playbackState == PlayingState) {
372+ m_playbackState = PausedState;
373+ Q_EMIT playbackStateChanged(m_playbackState);
374+ m_timer.stop();
375+ }
376+}
377+
378+void Audio::play()
379+{
380+ if (m_playbackState != PlayingState && m_source.isValid()) {
381+ m_playbackState = PlayingState;
382+ Q_EMIT playbackStateChanged(m_playbackState);
383+
384+ m_timer.start();
385+ }
386+}
387+
388+void Audio::stop()
389+{
390+ if (m_playbackState != StoppedState) {
391+ m_playbackState = StoppedState;
392+ Q_EMIT playbackStateChanged(m_playbackState);
393+ m_timer.stop();
394+ m_position = 0;
395+ Q_EMIT positionChanged(m_position);
396+ }
397+}
398+
399+void Audio::timerEvent()
400+{
401+ if (m_position + 1000 < m_duration) {
402+ m_position += 1000;
403+ Q_EMIT positionChanged(m_position);
404+ } else {
405+ stop();
406+ }
407+}
408
409=== added file 'tests/mocks/QtMultimedia/audio.h'
410--- tests/mocks/QtMultimedia/audio.h 1970-01-01 00:00:00 +0000
411+++ tests/mocks/QtMultimedia/audio.h 2013-11-27 11:27:38 +0000
412@@ -0,0 +1,78 @@
413+/*
414+ * Copyright (C) 2012,2013 Canonical, Ltd.
415+ *
416+ * This program is free software; you can redistribute it and/or modify
417+ * it under the terms of the GNU General Public License as published by
418+ * the Free Software Foundation; version 3.
419+ *
420+ * This program is distributed in the hope that it will be useful,
421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
423+ * GNU General Public License for more details.
424+ *
425+ * You should have received a copy of the GNU General Public License
426+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
427+ *
428+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
429+ */
430+
431+#ifndef MOCK_AUDIO_H
432+#define MOCK_AUDIO_H
433+
434+#include <QObject>
435+#include <QUrl>
436+#include <QTimer>
437+
438+class Audio: public QObject
439+{
440+ Q_OBJECT
441+ Q_ENUMS(PlaybackState)
442+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
443+ Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged)
444+ Q_PROPERTY(int position READ position NOTIFY positionChanged)
445+ Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
446+ Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
447+public:
448+ enum PlaybackState {
449+ PlayingState,
450+ PausedState,
451+ StoppedState
452+ };
453+
454+ explicit Audio(QObject *parent = 0);
455+
456+ QUrl source() const;
457+ void setSource(const QUrl &source);
458+
459+ PlaybackState playbackState() const;
460+
461+ int position() const;
462+
463+ int duration() const;
464+
465+ QString errorString() const;
466+
467+public Q_SLOTS:
468+ void pause();
469+ void play();
470+ void stop();
471+
472+Q_SIGNALS:
473+ void sourceChanged(const QUrl &source);
474+ void playbackStateChanged(PlaybackState playbackState);
475+ void positionChanged(int position);
476+ void durationChanged(int duration);
477+ void errorStringChanged(const QString &errorString);
478+
479+private Q_SLOTS:
480+ void timerEvent();
481+
482+private:
483+ QUrl m_source;
484+ PlaybackState m_playbackState;
485+ QTimer m_timer;
486+ int m_position;
487+ int m_duration;
488+};
489+
490+#endif
491
492=== added file 'tests/mocks/QtMultimedia/plugin.cpp'
493--- tests/mocks/QtMultimedia/plugin.cpp 1970-01-01 00:00:00 +0000
494+++ tests/mocks/QtMultimedia/plugin.cpp 2013-11-27 11:27:38 +0000
495@@ -0,0 +1,28 @@
496+/*
497+ * Copyright (C) 2012,2013 Canonical, Ltd.
498+ *
499+ * This program is free software; you can redistribute it and/or modify
500+ * it under the terms of the GNU General Public License as published by
501+ * the Free Software Foundation; version 3.
502+ *
503+ * This program is distributed in the hope that it will be useful,
504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
506+ * GNU General Public License for more details.
507+ *
508+ * You should have received a copy of the GNU General Public License
509+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
510+ *
511+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
512+ */
513+
514+#include "plugin.h"
515+#include "audio.h"
516+
517+#include <QtQml/qqml.h>
518+
519+void MockQtMultimediaPlugin::registerTypes(const char *uri)
520+{
521+ Q_ASSERT(uri == QLatin1String("QtMultimedia"));
522+ qmlRegisterType<Audio>(uri, 5, 0, "Audio");
523+}
524
525=== added file 'tests/mocks/QtMultimedia/plugin.h'
526--- tests/mocks/QtMultimedia/plugin.h 1970-01-01 00:00:00 +0000
527+++ tests/mocks/QtMultimedia/plugin.h 2013-11-27 11:27:38 +0000
528@@ -0,0 +1,34 @@
529+/*
530+ * Copyright (C) 2012,2013 Canonical, Ltd.
531+ *
532+ * This program is free software; you can redistribute it and/or modify
533+ * it under the terms of the GNU General Public License as published by
534+ * the Free Software Foundation; version 3.
535+ *
536+ * This program is distributed in the hope that it will be useful,
537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
539+ * GNU General Public License for more details.
540+ *
541+ * You should have received a copy of the GNU General Public License
542+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
543+ *
544+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
545+ */
546+
547+#ifndef MOCK_QTMULTIMEDIA_PLUGIN_H
548+#define MOCK_QTMULTIMEDIA_PLUGIN_H
549+
550+#include <QtQml/QQmlEngine>
551+#include <QtQml/QQmlExtensionPlugin>
552+
553+class MockQtMultimediaPlugin : public QQmlExtensionPlugin
554+{
555+ Q_OBJECT
556+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
557+
558+public:
559+ void registerTypes(const char *uri);
560+};
561+
562+#endif
563
564=== added file 'tests/mocks/QtMultimedia/qmldir'
565--- tests/mocks/QtMultimedia/qmldir 1970-01-01 00:00:00 +0000
566+++ tests/mocks/QtMultimedia/qmldir 2013-11-27 11:27:38 +0000
567@@ -0,0 +1,2 @@
568+module QtMultimedia
569+plugin QtMultimedia-qml
570
571=== modified file 'tests/qmltests/CMakeLists.txt'
572--- tests/qmltests/CMakeLists.txt 2013-11-19 09:43:35 +0000
573+++ tests/qmltests/CMakeLists.txt 2013-11-27 11:27:38 +0000
574@@ -49,6 +49,7 @@
575 add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
576 add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
577 add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
578+add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
579 add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
580 PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
581 add_qml_test(Greeter Tablet IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
582
583=== added directory 'tests/qmltests/Dash/Music'
584=== added file 'tests/qmltests/Dash/Music/tst_MusicPreview.qml'
585--- tests/qmltests/Dash/Music/tst_MusicPreview.qml 1970-01-01 00:00:00 +0000
586+++ tests/qmltests/Dash/Music/tst_MusicPreview.qml 2013-11-27 11:27:38 +0000
587@@ -0,0 +1,174 @@
588+/*
589+ * Copyright 2013 Canonical Ltd.
590+ *
591+ * This program is free software; you can redistribute it and/or modify
592+ * it under the terms of the GNU General Public License as published by
593+ * the Free Software Foundation; version 3.
594+ *
595+ * This program is distributed in the hope that it will be useful,
596+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
597+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
598+ * GNU General Public License for more details.
599+ *
600+ * You should have received a copy of the GNU General Public License
601+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
602+ */
603+
604+import QtQuick 2.0
605+import QtTest 1.0
606+import "../../../../Dash/Music"
607+import Unity.Test 0.1 as UT
608+import QtMultimedia 5.0
609+
610+Rectangle {
611+ id: root
612+ width: units.gu(60)
613+ height: units.gu(80)
614+ color: "lightgrey"
615+
616+ MusicPreview {
617+ id: musicPreview
618+ anchors.fill: parent
619+ isCurrent: true
620+
621+ previewData: QtObject {
622+ property string rendererName: "preview-music"
623+ property string title: "Music Preview"
624+ property string subtitle: "Subtitle"
625+ property string description: "This is the description"
626+ property string image: "../../tests/qmltests/Components/tst_LazyImage/square.png"
627+ property var actions: [
628+ { id: 123, displayName: "Play"},
629+ { id: 456, displayName: "Show in folder"}
630+ ]
631+ property var tracks: tracksModel2
632+ }
633+ }
634+
635+ ListModel {
636+ id: tracksModel0
637+ }
638+ ListModel {
639+ id: tracksModel1
640+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 1; title: "Some track name"; length: "0:30"}
641+ }
642+ ListModel {
643+ id: tracksModel2
644+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 1; title: "Some track name"; length: "0:30"}
645+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 2; title: "Some track name"; length: "0:30"}
646+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound2.ogg"; trackNo: 3; title: "Some other track name"; length: "1:23"}
647+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound3.ogg"; trackNo: 4; title: "And another one"; length: "123:45"}
648+ }
649+
650+ UT.UnityTestCase {
651+ name: "MusicPreviewTest"
652+ when: windowShown
653+
654+ function init() {
655+ waitForRendering(musicPreview);
656+ }
657+
658+ function test_tracks_data() {
659+ return [
660+ {tag: "0 tracks", tracksModel: tracksModel0, dividerVisible: false},
661+ {tag: "1 track", tracksModel: tracksModel1, dividerVisible: true},
662+ {tag: "4 track", tracksModel: tracksModel2, dividerVisible: true}
663+ ];
664+ }
665+
666+ function test_tracks(data) {
667+ musicPreview.previewData.tracks = data.tracksModel;
668+ waitForRendering(musicPreview);
669+
670+ var trackRepeater = findChild(musicPreview, "trackRepeater");
671+ compare(trackRepeater.count, data.tracksModel.count)
672+
673+ var topDivider = findChild(musicPreview, "topDivider");
674+ compare(topDivider.visible, data.dividerVisible);
675+
676+ for (var i = 0; i < data.tracksModel.count; ++i) {
677+ var trackItem = findChild(musicPreview, "trackItem" + i);
678+ var titleLabel = findChild(trackItem, "trackTitleLabel");
679+ compare(titleLabel.text, data.tracksModel.get(i).title)
680+ var timeLabel = findChild(trackItem, "timeLabel");
681+ compare(timeLabel.text, data.tracksModel.get(i).length)
682+ }
683+ }
684+
685+ function checkPlayerUri(index) {
686+ var modelFilename = musicPreview.previewData.tracks.get(index).uri.replace(/^.*[\\\/]/, '');
687+ var playerFilename = findInvisibleChild(musicPreview, "audioPlayer").source.toString().replace(/^.*[\\\/]/, '');
688+
689+ compare(modelFilename, playerFilename, "Player source is not set correctly.");
690+ }
691+
692+ function test_playback() {
693+ musicPreview.previewData.tracks = tracksModel2;
694+ waitForRendering(musicPreview);
695+
696+ var track0Item = findChild(musicPreview, "trackItem0");
697+ var track1Item = findChild(musicPreview, "trackItem1");
698+ var track2Item = findChild(musicPreview, "trackItem2");
699+
700+ var track0ProgressBar = findChild(track0Item, "progressBarFill");
701+ var track1ProgressBar = findChild(track1Item, "progressBarFill");
702+ var track2ProgressBar = findChild(track2Item, "progressBarFill");
703+
704+ var track0PlayButton = findChild(track0Item, "playButton");
705+ var track1PlayButton = findChild(track1Item, "playButton");
706+ var track2PlayButton = findChild(track2Item, "playButton");
707+
708+ var audioPlayer = findInvisibleChild(musicPreview, "audioPlayer");
709+
710+ // All progress bars must be hidden in the beginning
711+ compare(track0ProgressBar.visible, false);
712+ compare(track1ProgressBar.visible, false);
713+ compare(track2ProgressBar.visible, false);
714+
715+ // Playing track 0 should make progress bar 0 visible
716+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
717+
718+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
719+ checkPlayerUri(0);
720+
721+ tryCompare(track0ProgressBar, "visible", true);
722+ tryCompare(track1ProgressBar, "visible", false);
723+ tryCompare(track2ProgressBar, "visible", false);
724+
725+ // Clicking the button again should pause it. The progress bar should stay visible
726+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
727+ tryCompare(audioPlayer, "playbackState", Audio.PausedState);
728+ checkPlayerUri(0);
729+ tryCompare(track0ProgressBar, "visible", true);
730+
731+ // Continue playback
732+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
733+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
734+ checkPlayerUri(0);
735+
736+ // Playing track 1 should make progress bar 1 visible and hide progress bar 0 again
737+ mouseClick(track1PlayButton, track1PlayButton.width / 2, track1PlayButton.height / 2);
738+
739+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
740+ checkPlayerUri(1);
741+
742+ tryCompare(track0ProgressBar, "visible", false);
743+ tryCompare(track1ProgressBar, "visible", true);
744+ tryCompare(track2ProgressBar, "visible", false);
745+
746+ // Playing track 2 should make progress bar 1 visible and hide progress bar 0 again
747+ mouseClick(track2PlayButton, track2PlayButton.width / 2, track2PlayButton.height / 2);
748+
749+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
750+ checkPlayerUri(2);
751+
752+ tryCompare(track0ProgressBar, "visible", false);
753+ tryCompare(track1ProgressBar, "visible", false);
754+ tryCompare(track2ProgressBar, "visible", true);
755+
756+ // Switching away from this preview should make all players shut up!
757+ musicPreview.isCurrent = false
758+ tryCompare(audioPlayer, "playbackState", Audio.StoppedState);
759+ }
760+ }
761+}
762
763=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
764--- tests/qmltests/Dash/tst_GenericScopeView.qml 2013-11-19 10:44:14 +0000
765+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2013-11-27 11:27:38 +0000
766@@ -186,8 +186,18 @@
767 true);
768 tryCompare(nextPreviewItem, "progress", 1);
769 waitForRendering(nextPreviewItem);
770+ tryCompareFunction(function() {return nextPreviewItem.item !== null}, true);
771
772 checkArrowPosition(i);
773+
774+ // Make sure only the new one has isCurrent set to true
775+ compare(nextPreviewItem.item.isCurrent, true);
776+
777+ if (currentPreviewItem.item !== undefined && currentPreviewItem.item !== null) {
778+ compare(currentPreviewItem.item.isCurrent, false);
779+ }
780+
781+ currentPreviewItem = nextPreviewItem;
782 }
783 closePreview();
784 }

Subscribers

People subscribed via source and target branches