Merge lp:~music-app-dev/music-app/use-mediascanner2.0 into lp:music-app/trusty
- use-mediascanner2.0
- Merge into trusty
Status: | Merged | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Nicholas Skaggs | ||||||||||||||||||||
Approved revision: | 528 | ||||||||||||||||||||
Merged at revision: | 496 | ||||||||||||||||||||
Proposed branch: | lp:~music-app-dev/music-app/use-mediascanner2.0 | ||||||||||||||||||||
Merge into: | lp:music-app/trusty | ||||||||||||||||||||
Diff against target: |
4287 lines (+1018/-1352) 34 files modified
LibraryListModel.qml (+16/-89) LoginLastFM.qml (+0/-1) MusicAlbums.qml (+26/-22) MusicArtists.qml (+57/-14) MusicNowPlaying.qml (+12/-12) MusicPlaylists.qml (+4/-3) MusicSearch.qml (+22/-27) MusicStart.qml (+76/-33) MusicToolbar.qml (+4/-4) MusicTracks.qml (+28/-17) MusicaddtoPlaylist.qml (+8/-7) Player.qml (+10/-11) Style.qml (+4/-3) click/apparmor.json (+1/-1) click/manifest.json.in (+2/-3) common/AlbumsSheet.qml (+52/-25) common/BlurredBackground.qml (+9/-9) common/CoverRow.qml (+7/-3) common/Expander.qml (+4/-3) common/SongsSheet.qml (+37/-21) debian/control (+7/-6) meta-database.js (+8/-380) music-app.qml (+139/-375) playlists.js (+6/-7) plugins.json (+0/-5) po/com.ubuntu.music.pot (+68/-76) po/lv.po (+2/-1) tests/autopilot/music_app/__init__.py (+1/-1) tests/autopilot/music_app/content/mediascanner-2.0/mediastore.sql (+39/-0) tests/autopilot/music_app/content/mediascanner/mediaindex (+0/-10) tests/autopilot/music_app/emulators.py (+21/-2) tests/autopilot/music_app/tests/__init__.py (+242/-52) tests/autopilot/music_app/tests/test_music.py (+102/-126) worker-library-loader.js (+4/-3) |
||||||||||||||||||||
To merge this branch: | bzr merge lp:~music-app-dev/music-app/use-mediascanner2.0 | ||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
David Planella | Needs Information | ||
Review via email: mp+214140@code.launchpad.net |
Commit message
* Refactor app to use new Media Scanner 2.0 qml bindings and database
Description of the change
I propose we review and merge into this branch as we develop and test against the mediascanner2.0[1] code.
To install this use the typical cmake and 'sudo make install' as you normally would. I had some difficulties satisfying the cmake prerequisites. I should have written down everything I had to install, but I did not. You'll need to just walk through the CMakeLists.txt as you search for possible candidate packages in apt-get. If someone else could capture what needs to be installed that'd be great.
The best description of the currently available components and types [2] should be pretty complete. This needs to be reviewed as well, so we can provide feedback to the mediascanner team. If you can not install and test with the code, please at least review the mediascanner2.0 API and code to target any deficiencies early on.
[1] https:/
[2] http://
Nicholas Skaggs (nskaggs) wrote : | # |
Andrew Hayzen (ahayzen) wrote : | # |
Note for us and others watching :)
From a app/ui point of view, other than missing the genre section on the start page [0], this is ready.
However now the autopilot tests need to be rewritten to work with mediascanner2.
As a note currently you will need to install qtdeclarative5-
A further enhancement which would be nice to have before landing is the ability to set a fallback album art but this requires changes to mediascanner/
0 - For us to implement genres on the start screen we need GenresModel {} and filtering by a genre within the AlbumsModel and SongsModel.
Victor Thompson (vthompson) wrote : | # |
Currently there's an issue where the Thumbnailer is not working because it is not in the app's apparmor profile. Additionally, the error this causes prevents AP from being run. Once this issue is figured out r450 can be reverted.
David Planella (dpm) wrote : | # |
Hi Victor, thanks for figuring this one out. In terms of the error, is there a bug filed in Thumbnailer that we can track? Are the mediascanner folks aware of this issue?
Victor Thompson (vthompson) wrote : | # |
No bug at the moment that I'm aware of. It was suggested on IRC that I ask jdstrand today to see what might be needed.
Victor Thompson (vthompson) wrote : | # |
This is likely the bug to track that is blocking app confinement with Thumbnailer: lp:1303962
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:451
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 452. By Andrew Hayzen
-
* Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:452
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 453. By Victor Thompson
-
* Initial test updates for mediascanner migration.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:453
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 454. By Victor Thompson
-
Merge trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:454
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 455. By Victor Thompson
-
Fix pyflakes error
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:455
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 456. By Victor Thompson
-
Fix bad merge conflict resolution
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:456
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 457. By Victor Thompson
-
empty
- 458. By Victor Thompson
-
Fix unused variable
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:457
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:458
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 459. By Victor Thompson
-
Merge trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:459
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 460. By Victor Thompson
-
Update test_play_
pause_library test
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:460
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 461. By Andrew Hayzen
-
* Fix for test_play_
pause_library touching indicators
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:461
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 462. By Victor Thompson
-
Find new customBackButton
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:462
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 463. By Victor Thompson
-
Patch db
- 464. By Andrew Hayzen
-
* Fixes for Pep8
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:463
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:464
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 465. By Victor Thompson
-
Patch SQLite DB.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:465
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 466. By Victor Thompson
-
* Fix play button on device
* Fix check for playing
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:466
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 467. By Victor Thompson
-
Test for only backButton
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:467
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 468. By Andrew Hayzen
-
* Use sortFilterModel to correctly sort Albums and Tracks
* Fix issue of blank album art in recent
* Correctly drop metadata table
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:468
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 469. By Andrew Hayzen
-
* Move all model.art/
model.cover to use model.artist and model.album to construct a image:// url - 470. By Andrew Hayzen
-
* Fix for incorrect tag for artist in image://
- 471. By Victor Thompson
-
Re-write test_play_
pause_library test - 472. By Victor Thompson
-
Use new 14.10-dev1 framework
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:469
http://
Executed test runs:
UNSTABLE: http://
deb: http://
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 473. By Andrew Hayzen
-
* Fix for cover art
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:472
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:473
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 474. By Andrew Hayzen
-
* Fix for pyflakes
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:474
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 475. By Andrew Hayzen
-
* Revert framework bump for testing
- 476. By Andrew Hayzen
-
* Fix for blur background empty at startup
- 477. By Andrew Hayzen
-
* Bump framework to ubuntu-
sdk-14. 10-qml- dev1
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:476
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:477
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 478. By Victor Thompson
-
* Update app armor for confinement
* Update policy version
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:478
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 479. By Victor Thompson
-
Update copyright
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:479
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:479
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 480. By Andrew Hayzen
-
* Fix for patching home_dir
- 481. By Nicholas Skaggs
-
tweak env patching apparmor setup
- 482. By Nicholas Skaggs
-
simplify logic per thomi for local_location_qml
- 483. By Nicholas Skaggs
-
revert local_location tweak
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:480
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 484. By Andrew Hayzen
-
* Readd genre support
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:484
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:484
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 485. By Andrew Hayzen
-
* Ensure that genre is set to undefined when filtering by album
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:485
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
Just and update on the apparmor info; we are dependent on the apparmor changes for mediascanner which I guess are still being worked? The policy for this to allow testing has gotten quite complex. We may be forced to go back to the old method of backing up files if this has to land before we can get apparmor playing nicely with the tests.
- 486. By Andrew Hayzen
-
* Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:486
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 487. By Nicholas Skaggs
-
update ap env isolation (mediascanner still will whine)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:487
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 488. By Victor Thompson
-
Add gstreamer dependencies needed for the app to work on Utopic desktop.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:488
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 489. By Andrew Hayzen
-
* Fix to stop genres incorrectly appearing in recent if play all was selected
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:489
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 490. By Victor Thompson
-
Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:490
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 491. By Victor Thompson
-
Fix play all of an album from the Artist albums sheet
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:491
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 492. By Andrew Hayzen
-
* Add thumbnailer-service as depends for now to resolve issues on desktop
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:492
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Pope 🍺🐧🐱 🦄 (popey) wrote : | # |
Just tested this on my desktop, and when mediascanner-2.0 service isn't running it crashes..
alan@deep-
unity::
Could not determine application identifier. HUD will not work properly.
Provide your application identifier in $APP_ID environment variable.
Debug: Queue: Now has: 0 tracks
Debug: onCountChanged: 0
terminate called after throwing an instance of 'std::runtime_
what(): org.freedesktop
Aborted (core dumped)
When mediascanner-2.0 _is_ running, it also crashes but took a little longer and crashed slightly differently.
alan@deep-
unity::
Could not determine application identifier. HUD will not work properly.
Provide your application identifier in $APP_ID environment variable.
Debug: Queue: Now has: 0 tracks
Debug: onCountChanged: 0
terminate called after throwing an instance of 'std::runtime_
what(): com.canonical.
Aborted (core dumped)
- 493. By Nicholas Skaggs
-
revert to using backup and restore for database and Music folders
- 494. By Nicholas Skaggs
-
fix flake8, also backup mediascanner path
Nicholas Skaggs (nskaggs) wrote : | # |
I left the patching/
Note, that should a test fail the restore might not work properly. Caveat emptor.
- 495. By Nicholas Skaggs
-
set /home to be ~/
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:495
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 496. By Nicholas Skaggs
-
wip
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:496
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 497. By Nicholas Skaggs
-
undo the backup/restore. it's just not an option
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:497
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 498. By Andrew Hayzen
-
* Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:498
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:498
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Andrew Hayzen (ahayzen) wrote : | # |
#blocked mediascanner2 bug 1326753
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:498
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 499. By Victor Thompson
-
Limiting SongsModels to 500 to ensure they at least load
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:499
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 500. By Andrew Hayzen
-
* Hack to limit all SongsModels to 500 tracks
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:500
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 501. By Victor Thompson
-
Merge trunk
Nicholas Skaggs (nskaggs) wrote : | # |
The issues with music no longer mocking are baffling; but music is not alone. Calendar which has a similar implementation, is no longer mocking home properly either. AFAICT, the proper environment variables are being set, and music sees them. Since qml is unable to dump env vars, I used reminders to verify autopilot was patching properly (needed qt and reminders is compiled). It's not 100%, but seems reasonable. If you attempt to get the env var from within a test, it too reflects the proper directory. So it seems practical that the app itself is being launched with the proper env variable set.
For the moment, I'm ignoring the issues present with running and mocking on the phone; the app seemingly still looks in your actual home directory despite being told it's somewhere else.
So, has something else changed that would cause the app to look somewhere else for where HOME is?
Nicholas Skaggs (nskaggs) wrote : | # |
Or perhaps does the app now need it's environment set yet another way, or another variable set?
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:501
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:501
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Victor Thompson (vthompson) wrote : | # |
Personally, I assumed it had to do with dbus changes in mediascanner2. Isn't the app in the store/image mocking? That appears to work. I hate making concessions, but we might want to go back to copying off the Music dir, but in addition to that maybe we could run each test as follows:
1) stop mediascanner2*
2) copy/save user's Music dir
3) move test songs to ~/Music
4) start mediascanner2
5) sleep for a predefined period
6) stop mediascanner2
7) run test
8) restore user's Music dir
*Note that subsequent tests will already have mediascanner2 stopped. This will prevent the service from needlessly rescanning the users music--which could take some time. This would mean that the user should either start mediascanner2 to rebuild their music library to use the app or reboot. Everything should then work.
- 502. By Victor Thompson
-
Fix destructive tests
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:502
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 503. By Victor Thompson
-
Stop and start mediascanner2 and also wait 10 seconds
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:503
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 504. By Nicholas Skaggs
-
all the hackiness at once
- 505. By Nicholas Skaggs
-
slightly saner version
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:505
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 506. By Nicholas Skaggs
-
pull out dbus launch
- 507. By Andrew Hayzen
-
* Add cleanups to autopilot
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:507
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:509
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 508. By Nicholas Skaggs
-
new fake db based on schema 6
- 509. By Nicholas Skaggs
-
rebase
- 510. By Nicholas Skaggs
-
removing debugging prints and waits; fix for dbus call
- 511. By Nicholas Skaggs
-
remove extraneous function
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:511
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 512. By Nicholas Skaggs
-
remove sys.exit from test
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:512
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 513. By Nicholas Skaggs
-
remove extra comment
- 514. By Nicholas Skaggs
-
merge back andrew's branch using backup/restore instead of isolation
- 515. By Nicholas Skaggs
-
more comments
- 516. By Nicholas Skaggs
-
merged victor's artist fix
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:516
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 517. By Nicholas Skaggs
-
add back backup/restore to create_
music_libraray - 518. By Nicholas Skaggs
-
flake8 goodness
- 519. By Victor Thompson
-
Cleanup
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:517
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 520. By Victor Thompson
-
revert last commit
- 521. By Nicholas Skaggs
-
remove extra cleanup steps
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:520
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 522. By Nicholas Skaggs
-
fix up isolation code
- 523. By Nicholas Skaggs
-
add back _patch_
mediascanner_ home
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:523
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 524. By Nicholas Skaggs
-
simplify backup/restore code
- 525. By Nicholas Skaggs
-
simplification, better expansion, pep8 fixes
- 526. By Victor Thompson
-
Update calls
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:525
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:526
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 527. By Victor Thompson
-
remove time
- 528. By Nicholas Skaggs
-
switch to subprocess
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:527
http://
Executed test runs:
None: http://
None: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
This is the merge that doesn't end, it goes on and on my friend. Some people tried to merge it not knowing what it was, but they'll continue trying to merge forever just because, This is the mergeThis is the merge that doesn't end that doesn't end . . .
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Preview Diff
1 | === modified file 'LibraryListModel.qml' |
2 | --- LibraryListModel.qml 2014-02-22 21:46:04 +0000 |
3 | +++ LibraryListModel.qml 2014-06-19 01:49:30 +0000 |
4 | @@ -1,6 +1,8 @@ |
5 | /* |
6 | - * Copyright (C) 2013 Victor Thompson <victor.thompson@gmail.com> |
7 | - * Daniel Holm <d.holmen@gmail.com> |
8 | + * Copyright (C) 2013, 2014 |
9 | + * Andrew Hayzen <ahayzen@gmail.com> |
10 | + * Daniel Holm <d.holmen@gmail.com> |
11 | + * Victor Thompson <victor.thompson@gmail.com> |
12 | * |
13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by |
15 | @@ -21,7 +23,11 @@ |
16 | import "playlists.js" as Playlists |
17 | |
18 | Item { |
19 | - property ListModel model : ListModel { id: libraryModel } |
20 | + id: libraryListModelItem |
21 | + property ListModel model : ListModel { |
22 | + id: libraryModel |
23 | + property var linkLibraryListModel: libraryListModelItem |
24 | + } |
25 | property alias count: libraryModel.count |
26 | property var query: null |
27 | property var param: null |
28 | @@ -37,6 +43,13 @@ |
29 | } |
30 | } |
31 | |
32 | + /* Pretent to be like a mediascanner2 listmodel */ |
33 | + property alias rowCount: libraryModel.count |
34 | + |
35 | + function get(index, role) { |
36 | + return model.get(index); |
37 | + } |
38 | + |
39 | WorkerScript { |
40 | id: worker |
41 | source: "worker-library-loader.js" |
42 | @@ -105,66 +118,6 @@ |
43 | return -1; |
44 | } |
45 | |
46 | - function populate() { |
47 | - console.log("called LibraryListModel::populate()") |
48 | - |
49 | - // Save query for queue |
50 | - query = Library.getAll |
51 | - param = null |
52 | - |
53 | - worker.list = Library.getAll(); |
54 | - } |
55 | - |
56 | - function filterArtists() { |
57 | - console.log("called LibraryListModel::filterArtists()") |
58 | - |
59 | - // Save query for queue |
60 | - query = Library.getArtists |
61 | - param = null |
62 | - |
63 | - worker.list = Library.getArtists(); |
64 | - } |
65 | - |
66 | - function filterArtistTracks(artist) { |
67 | - console.log("called LibraryListModel::filterArtistTracks()") |
68 | - |
69 | - // Save query for queue |
70 | - query = Library.getArtistTracks |
71 | - param = artist |
72 | - |
73 | - worker.list = Library.getArtistTracks(artist); |
74 | - } |
75 | - |
76 | - function filterArtistAlbums(artist) { |
77 | - console.log("called LibraryListModel::filterArtistAlbums()") |
78 | - |
79 | - // Save query for queue |
80 | - query = Library.getArtistAlbums |
81 | - param = artist |
82 | - |
83 | - worker.list = Library.getArtistAlbums(artist); |
84 | - } |
85 | - |
86 | - function filterAlbums() { |
87 | - console.log("called LibraryListModel::filterAlbums()") |
88 | - |
89 | - // Save query for queue |
90 | - query = Library.getAlbums |
91 | - param = null |
92 | - |
93 | - worker.list = Library.getAlbums(); |
94 | - } |
95 | - |
96 | - function filterAlbumTracks(album) { |
97 | - console.log("called LibraryListModel::filterAlbumTracks()") |
98 | - |
99 | - // Save query for queue |
100 | - query = Library.getAlbumTracks |
101 | - param = album |
102 | - |
103 | - worker.list = Library.getAlbumTracks(album); |
104 | - } |
105 | - |
106 | function filterPlaylists() { |
107 | console.log("called LibraryListModel::filterPlaylistTracks()") |
108 | |
109 | @@ -195,36 +148,10 @@ |
110 | worker.list = Library.getRecent(); |
111 | } |
112 | |
113 | - function filterGenres() { |
114 | - console.log("called LibraryListModel::filterGenres()") |
115 | - |
116 | - // Save query for queue |
117 | - query = Library.getGenres |
118 | - param = null |
119 | - |
120 | - worker.list = Library.getGenres(); |
121 | - } |
122 | - |
123 | - function filterGenreTracks(genre) { |
124 | - console.log("called LibraryListModel::filterGenreTracks()") |
125 | - |
126 | - // Save query for queue |
127 | - query = Library.getGenreTracks |
128 | - param = genre |
129 | - |
130 | - worker.list = Library.getGenreTracks(genre); |
131 | - } |
132 | - |
133 | function clear() { |
134 | if (worker.list !== null) |
135 | { |
136 | worker.sendMessage({'clear': true, 'model': libraryModel}) |
137 | } |
138 | } |
139 | - |
140 | - function filterSearch(searchQuery) { |
141 | - query = Library.search |
142 | - param = searchQuery |
143 | - worker.list = Library.search(searchQuery) |
144 | - } |
145 | } |
146 | |
147 | === modified file 'LoginLastFM.qml' |
148 | --- LoginLastFM.qml 2014-01-11 17:41:20 +0000 |
149 | +++ LoginLastFM.qml 2014-06-19 01:49:30 +0000 |
150 | @@ -24,7 +24,6 @@ |
151 | import QtQuick.LocalStorage 2.0 |
152 | import QtQuick.XmlListModel 2.0 |
153 | import "settings.js" as Settings |
154 | -import "meta-database.js" as Library |
155 | import "scrobble.js" as Scrobble |
156 | |
157 | // Last.fm login dialog |
158 | |
159 | === modified file 'MusicAlbums.qml' |
160 | --- MusicAlbums.qml 2014-04-17 14:42:51 +0000 |
161 | +++ MusicAlbums.qml 2014-06-19 01:49:30 +0000 |
162 | @@ -1,6 +1,8 @@ |
163 | /* |
164 | - * Copyright (C) 2013 Victor Thompson <victor.thompson@gmail.com> |
165 | - * Daniel Holm <d.holmen@gmail.com> |
166 | + * Copyright (C) 2013, 2014 |
167 | + * Andrew Hayzen <ahayzen@gmail.com> |
168 | + * Daniel Holm <d.holmen@gmail.com> |
169 | + * Victor Thompson <victor.thompson@gmail.com> |
170 | * |
171 | * This program is free software; you can redistribute it and/or modify |
172 | * it under the terms of the GNU General Public License as published by |
173 | @@ -17,14 +19,16 @@ |
174 | |
175 | import QtQuick 2.0 |
176 | import Ubuntu.Components 0.1 |
177 | +import Ubuntu.Components 1.1 as Toolkit |
178 | import Ubuntu.Components.ListItems 0.1 |
179 | import Ubuntu.Components.Popups 0.1 |
180 | import Ubuntu.Components.ListItems 0.1 as ListItem |
181 | +import Ubuntu.MediaScanner 0.1 |
182 | +import Ubuntu.Thumbnailer 0.1 |
183 | import QtMultimedia 5.0 |
184 | import QtQuick.LocalStorage 2.0 |
185 | import QtGraphicalEffects 1.0 |
186 | import "settings.js" as Settings |
187 | -import "meta-database.js" as Library |
188 | import "playlists.js" as Playlists |
189 | import "common" |
190 | |
191 | @@ -59,21 +63,23 @@ |
192 | anchors.bottomMargin: units.gu(1) |
193 | cellHeight: height/3 |
194 | cellWidth: height/3 |
195 | - model: albumModel.model |
196 | + model: Toolkit.SortFilterModel { |
197 | + id: albumsModelFilter |
198 | + property alias rowCount: albumsModel.rowCount |
199 | + model: AlbumsModel { |
200 | + id: albumsModel |
201 | + store: musicStore |
202 | + } |
203 | + sort.property: "title" |
204 | + sort.order: Qt.AscendingOrder |
205 | + } |
206 | + |
207 | delegate: albumDelegate |
208 | flow: GridView.TopToBottom |
209 | |
210 | Component { |
211 | id: albumDelegate |
212 | Item { |
213 | - property string artist: model.artist |
214 | - property string album: model.album |
215 | - property string title: model.title |
216 | - property string cover: model.cover !== "" ? model.cover : Qt.resolvedUrl("images/music-app-cover@30.png") |
217 | - property string length: model.length |
218 | - property string file: model.file |
219 | - property string year: model.year |
220 | - |
221 | id: albumItem |
222 | height: albumlist.cellHeight - units.gu(1) |
223 | width: albumlist.cellHeight - units.gu(1) |
224 | @@ -85,7 +91,7 @@ |
225 | image: Image { |
226 | id: icon |
227 | fillMode: Image.Stretch |
228 | - source: cover |
229 | + source: "image://albumart/artist=" + model.artist + "&album=" + model.title |
230 | onStatusChanged: { |
231 | if (status === Image.Error) { |
232 | source = Qt.resolvedUrl("images/music-app-cover@30.png") |
233 | @@ -118,7 +124,7 @@ |
234 | anchors.rightMargin: units.gu(1) |
235 | color: styleMusic.nowPlaying.labelSecondaryColor |
236 | elide: Text.ElideRight |
237 | - text: artist |
238 | + text: model.artist |
239 | fontSize: "x-small" |
240 | } |
241 | Label { |
242 | @@ -131,7 +137,7 @@ |
243 | anchors.rightMargin: units.gu(1) |
244 | color: styleMusic.common.white |
245 | elide: Text.ElideRight |
246 | - text: album |
247 | + text: model.title |
248 | fontSize: "small" |
249 | } |
250 | } |
251 | @@ -143,14 +149,12 @@ |
252 | onPressAndHold: { |
253 | } |
254 | onClicked: { |
255 | - albumTracksModel.filterAlbumTracks(album) |
256 | - |
257 | - songsSheet.line1 = artist |
258 | - songsSheet.line2 = album |
259 | + songsSheet.album = model.title; |
260 | + songsSheet.genre = undefined |
261 | + songsSheet.line1 = model.artist |
262 | + songsSheet.line2 = model.title |
263 | songsSheet.isAlbum = true |
264 | - songsSheet.file = file |
265 | - songsSheet.year = year |
266 | - songsSheet.covers = [cover] |
267 | + songsSheet.covers = [{author: model.artist, album: model.title}] |
268 | PopupUtils.open(songsSheet.sheet) |
269 | } |
270 | } |
271 | |
272 | === modified file 'MusicArtists.qml' |
273 | --- MusicArtists.qml 2014-05-19 23:13:39 +0000 |
274 | +++ MusicArtists.qml 2014-06-19 01:49:30 +0000 |
275 | @@ -1,6 +1,8 @@ |
276 | /* |
277 | - * Copyright (C) 2013 Victor Thompson <victor.thompson@gmail.com> |
278 | - * Daniel Holm <d.holmen@gmail.com> |
279 | + * Copyright (C) 2013, 2014 |
280 | + * Andrew Hayzen <ahayzen@gmail.com> |
281 | + * Daniel Holm <d.holmen@gmail.com> |
282 | + * Victor Thompson <victor.thompson@gmail.com> |
283 | * |
284 | * This program is free software; you can redistribute it and/or modify |
285 | * it under the terms of the GNU General Public License as published by |
286 | @@ -20,6 +22,8 @@ |
287 | import Ubuntu.Components.ListItems 0.1 |
288 | import Ubuntu.Components.Popups 0.1 |
289 | import Ubuntu.Components.ListItems 0.1 as ListItem |
290 | +import Ubuntu.MediaScanner 0.1 |
291 | +import Ubuntu.Thumbnailer 0.1 |
292 | import QtMultimedia 5.0 |
293 | import QtQuick.LocalStorage 2.0 |
294 | import "settings.js" as Settings |
295 | @@ -47,7 +51,12 @@ |
296 | id: artistlist |
297 | anchors.fill: parent |
298 | anchors.bottomMargin: musicToolbar.mouseAreaOffset + musicToolbar.minimizedHeight |
299 | - model: artistModel.model |
300 | + model: ArtistsModel { |
301 | + id: artistsModel |
302 | + albumArtists: true |
303 | + store: musicStore |
304 | + } |
305 | + |
306 | delegate: artistDelegate |
307 | |
308 | Component { |
309 | @@ -55,9 +64,46 @@ |
310 | |
311 | ListItem.Standard { |
312 | id: track |
313 | - property string artist: model.artist |
314 | height: styleMusic.common.itemHeight |
315 | |
316 | + AlbumsModel { |
317 | + id: albumArtistModel |
318 | + albumArtist: model.artist |
319 | + store: musicStore |
320 | + } |
321 | + |
322 | + Repeater { |
323 | + id: albumArtistModelRepeater |
324 | + model: albumArtistModel |
325 | + delegate: Item { |
326 | + property string author: model.artist |
327 | + property string album: model.title |
328 | + } |
329 | + property var covers: [] |
330 | + signal finished() |
331 | + |
332 | + onFinished: { |
333 | + coverRow.count = count |
334 | + coverRow.covers = covers |
335 | + } |
336 | + onItemAdded: { |
337 | + covers.push({author: item.author, album: item.album}); |
338 | + |
339 | + if (index === count - 1) { |
340 | + finished(); |
341 | + } |
342 | + } |
343 | + } |
344 | + |
345 | + SongsModel { |
346 | + id: songArtistModel |
347 | + albumArtist: model.artist |
348 | + // HACK: Temporarily setting limit to 500 to ensure model |
349 | + // is populated. See lp:1326753 |
350 | + limit: 500 |
351 | + store: musicStore |
352 | + } |
353 | + |
354 | CoverRow { |
355 | id: coverRow |
356 | anchors { |
357 | @@ -65,9 +111,10 @@ |
358 | left: parent.left |
359 | margins: units.gu(1) |
360 | } |
361 | - count: parseInt(Library.getArtistCovers(artist).length) |
362 | + |
363 | + count: 0 |
364 | size: styleMusic.common.albumSize |
365 | - covers: Library.getArtistCovers(artist) |
366 | + covers: [] |
367 | } |
368 | |
369 | Label { |
370 | @@ -86,7 +133,7 @@ |
371 | rightMargin: units.gu(1.5) |
372 | } |
373 | elide: Text.ElideRight |
374 | - text: artist |
375 | + text: model.artist |
376 | } |
377 | |
378 | Label { |
379 | @@ -103,8 +150,7 @@ |
380 | rightMargin: units.gu(1.5) |
381 | } |
382 | elide: Text.ElideRight |
383 | - // model for number of albums? |
384 | - text: i18n.tr("%1 album", "%1 albums", Library.getArtistAlbumCount(artist)).arg(Library.getArtistAlbumCount(artist)) |
385 | + text: i18n.tr("%1 album", "%1 albums", albumArtistModel.rowCount).arg(albumArtistModel.rowCount) |
386 | } |
387 | |
388 | Label { |
389 | @@ -121,7 +167,7 @@ |
390 | rightMargin: units.gu(1.5) |
391 | } |
392 | elide: Text.ElideRight |
393 | - text: i18n.tr("%1 song", "%1 songs", Library.getArtistTracks(artist).length).arg(Library.getArtistTracks(artist).length) |
394 | + text: i18n.tr("%1 song", "%1 songs", songArtistModel.rowCount).arg(songArtistModel.rowCount) |
395 | } |
396 | onFocusChanged: { |
397 | } |
398 | @@ -132,14 +178,11 @@ |
399 | onPressAndHold: { |
400 | } |
401 | onClicked: { |
402 | - artistAlbumsModel.filterArtistAlbums(artist) |
403 | - artistSheet.artist = artist |
404 | + artistSheet.artist = model.artist |
405 | artistSheet.covers = coverRow.covers |
406 | PopupUtils.open(artistSheet.sheet) |
407 | } |
408 | } |
409 | - Component.onCompleted: { |
410 | - } |
411 | } |
412 | } |
413 | } |
414 | |
415 | === modified file 'MusicNowPlaying.qml' |
416 | --- MusicNowPlaying.qml 2014-05-08 22:58:35 +0000 |
417 | +++ MusicNowPlaying.qml 2014-06-19 01:49:30 +0000 |
418 | @@ -1,7 +1,8 @@ |
419 | /* |
420 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
421 | - * Daniel Holm <d.holmen@gmail.com> |
422 | - * Victor Thompson <victor.thompson@gmail.com> |
423 | + * Copyright (C) 2013, 2014 |
424 | + * Andrew Hayzen <ahayzen@gmail.com> |
425 | + * Daniel Holm <d.holmen@gmail.com> |
426 | + * Victor Thompson <victor.thompson@gmail.com> |
427 | * |
428 | * This program is free software; you can redistribute it and/or modify |
429 | * it under the terms of the GNU General Public License as published by |
430 | @@ -22,9 +23,9 @@ |
431 | import QtQuick.LocalStorage 2.0 |
432 | import Ubuntu.Components 0.1 |
433 | import Ubuntu.Components.ListItems 0.1 as ListItem |
434 | +import Ubuntu.Thumbnailer 0.1 |
435 | import "common" |
436 | import "common/ExpanderItems" |
437 | -import "meta-database.js" as Library |
438 | import "settings.js" as Settings |
439 | |
440 | Page { |
441 | @@ -254,8 +255,8 @@ |
442 | |
443 | onClicked: { |
444 | collapseSwipeDelete(-1); // collapse all expands |
445 | - customdebug("File: " + model.file) // debugger |
446 | - trackClicked(trackQueue, index) // play track |
447 | + customdebug("File: " + model.filename) // debugger |
448 | + trackQueueClick(index); // toggle track state |
449 | } |
450 | |
451 | onMouseXChanged: { |
452 | @@ -309,7 +310,7 @@ |
453 | { |
454 | collapseSwipeDelete(-1); // collapse all swipedeletes |
455 | collapseExpand(); // collapse all |
456 | - customdebug("Pressed and held queued track "+model.file) |
457 | + customdebug("Pressed and held queued track "+model.filename) |
458 | queuelist.state = "reorder"; // enable reordering state |
459 | trackContainerReorderAnimation.start(); |
460 | } |
461 | @@ -490,7 +491,6 @@ |
462 | |
463 | // Remove item from queue and clear caches |
464 | trackQueue.model.remove(index); |
465 | - queueChanged = true; |
466 | } |
467 | } |
468 | } |
469 | @@ -537,7 +537,7 @@ |
470 | height: (queueListItem.state === "current" ? queuelist.currentHeight - units.gu(8) : queuelist.normalHeight) - units.gu(2) |
471 | width: height |
472 | image: Image { |
473 | - source: cover !== "" ? cover : "images/music-app-cover@30.png" |
474 | + source: "image://albumart/artist=" + model.author + "&album=" + model.album |
475 | onStatusChanged: { |
476 | if (status === Image.Error) { |
477 | source = Qt.resolvedUrl("images/music-app-cover@30.png") |
478 | @@ -579,7 +579,7 @@ |
479 | color: styleMusic.nowPlaying.labelSecondaryColor |
480 | elide: Text.ElideRight |
481 | height: units.gu(1) |
482 | - text: artist |
483 | + text: model.author |
484 | fontSize: 'small' |
485 | width: parent.width - trackImage.width - units.gu(3.5) |
486 | x: trackImage.x + trackImage.width + units.gu(1) |
487 | @@ -591,7 +591,7 @@ |
488 | color: styleMusic.common.white |
489 | elide: Text.ElideRight |
490 | height: units.gu(1) |
491 | - text: title |
492 | + text: model.title |
493 | fontSize: 'medium' |
494 | width: parent.width - trackImage.width - units.gu(3.5) |
495 | x: trackImage.x + trackImage.width + units.gu(1) |
496 | @@ -603,7 +603,7 @@ |
497 | color: styleMusic.nowPlaying.labelSecondaryColor |
498 | elide: Text.ElideRight |
499 | height: units.gu(1) |
500 | - text: album |
501 | + text: model.album |
502 | fontSize: 'x-small' |
503 | width: parent.width - trackImage.width - units.gu(3.5) |
504 | x: trackImage.x + trackImage.width + units.gu(1) |
505 | |
506 | === modified file 'MusicPlaylists.qml' |
507 | --- MusicPlaylists.qml 2014-04-26 17:13:02 +0000 |
508 | +++ MusicPlaylists.qml 2014-06-19 01:49:30 +0000 |
509 | @@ -1,6 +1,8 @@ |
510 | /* |
511 | - * Copyright (C) 2013 Daniel Holm <d.holmen@gmail.com> |
512 | - Victor Thompson <victor.thompson@gmail.com> |
513 | + * Copyright (C) 2013, 2014 |
514 | + * Andrew Hayzen <ahayzen@gmail.com> |
515 | + * Daniel Holm <d.holmen@gmail.com> |
516 | + * Victor Thompson <victor.thompson@gmail.com> |
517 | * |
518 | * |
519 | * This program is free software; you can redistribute it and/or modify |
520 | @@ -24,7 +26,6 @@ |
521 | import QtMultimedia 5.0 |
522 | import QtQuick.LocalStorage 2.0 |
523 | import "settings.js" as Settings |
524 | -import "meta-database.js" as Library |
525 | import "scrobble.js" as Scrobble |
526 | import "playlists.js" as Playlists |
527 | import "common" |
528 | |
529 | === modified file 'MusicSearch.qml' |
530 | --- MusicSearch.qml 2014-05-14 23:39:19 +0000 |
531 | +++ MusicSearch.qml 2014-06-19 01:49:30 +0000 |
532 | @@ -1,7 +1,8 @@ |
533 | /* |
534 | - * Copyright (C) 2014 Andrew Hayzen <ahayzen@gmail.com> |
535 | - * Daniel Holm <d.holmen@gmail.com> |
536 | - * Victor Thompson <victor.thompson@gmail.com> |
537 | + * Copyright (C) 2013, 2014 |
538 | + * Andrew Hayzen <ahayzen@gmail.com> |
539 | + * Daniel Holm <d.holmen@gmail.com> |
540 | + * Victor Thompson <victor.thompson@gmail.com> |
541 | * |
542 | * This program is free software; you can redistribute it and/or modify |
543 | * it under the terms of the GNU General Public License as published by |
544 | @@ -21,9 +22,10 @@ |
545 | import Ubuntu.Components 0.1 |
546 | import Ubuntu.Components.ListItems 0.1 as ListItem |
547 | import Ubuntu.Components.Popups 0.1 |
548 | +import Ubuntu.MediaScanner 0.1 |
549 | +import Ubuntu.Thumbnailer 0.1 |
550 | import QtQuick.LocalStorage 2.0 |
551 | import "playlists.js" as Playlists |
552 | -import "meta-database.js" as Library |
553 | import "common" |
554 | import "common/ExpanderItems" |
555 | |
556 | @@ -93,18 +95,13 @@ |
557 | // Provide a small pause before search |
558 | Timer { |
559 | id: searchTimer |
560 | - interval: 1500 |
561 | + interval: 500 |
562 | repeat: false |
563 | onTriggered: { |
564 | - if(searchField.text) { |
565 | - searchModel.filterSearch(searchField.text) // query the databse |
566 | - searchActivity.running = true // start the activity indicator |
567 | - } |
568 | - else { |
569 | - customdebug("No search terms.") |
570 | - searchModel.filterSearch("empty somehow?") |
571 | - } |
572 | - indicatorTimer.start() |
573 | + songsSearchModel.query = searchField.text; |
574 | + searchActivity.running = true // start the activity indicator |
575 | + |
576 | + indicatorTimer.start() |
577 | } |
578 | } |
579 | // and onother one for the indicator |
580 | @@ -133,6 +130,7 @@ |
581 | width: parent.width |
582 | height: parent.height |
583 | color: "transparent" |
584 | + visible: searchField.text |
585 | clip: true |
586 | anchors { |
587 | top: searchField.bottom |
588 | @@ -147,7 +145,10 @@ |
589 | objectName: "searchtrackview" |
590 | width: parent.width |
591 | height: parent.width |
592 | - model: searchModel.model |
593 | + model: SongsSearchModel { |
594 | + id: songsSearchModel |
595 | + store: musicStore |
596 | + } |
597 | |
598 | onMovementStarted: { |
599 | searchTrackView.forceActiveFocus() |
600 | @@ -158,18 +159,12 @@ |
601 | objectName: "playlist" |
602 | width: parent.width |
603 | height: styleMusic.common.itemHeight |
604 | - property string title: model.title |
605 | - property string artist: model.artist |
606 | - property string file: model.file |
607 | - property string album: model.album |
608 | - property string cover: model.cover |
609 | - property string genre: model.genre |
610 | |
611 | onClicked: { |
612 | console.debug("Debug: "+title+" added to queue") |
613 | // now play this track, but keep current queue |
614 | trackQueue.append(model) |
615 | - trackClicked(trackQueue, trackQueue.model.count - 1, true) |
616 | + trackQueueClick(trackQueue.model.count - 1); |
617 | onDoneClicked: PopupUtils.close(searchTrack) |
618 | } |
619 | |
620 | @@ -189,7 +184,7 @@ |
621 | width: styleMusic.common.albumSize |
622 | height: styleMusic.common.albumSize |
623 | image: Image { |
624 | - source: cover !== "" ? cover : Qt.resolvedUrl("images/music-app-cover@30.png") |
625 | + source: "image://albumart/artist=" + model.author + "&album=" + model.title |
626 | onStatusChanged: { |
627 | if (status === Image.Error) { |
628 | source = Qt.resolvedUrl("images/music-app-cover@30.png") |
629 | @@ -211,7 +206,7 @@ |
630 | anchors.right: parent.right |
631 | anchors.rightMargin: units.gu(1.5) |
632 | elide: Text.ElideRight |
633 | - text: artist |
634 | + text: model.author |
635 | } |
636 | Label { |
637 | id: trackTitle |
638 | @@ -227,7 +222,7 @@ |
639 | anchors.right: parent.right |
640 | anchors.rightMargin: units.gu(1.5) |
641 | elide: Text.ElideRight |
642 | - text: title |
643 | + text: model.title |
644 | } |
645 | Label { |
646 | id: trackAlbum |
647 | @@ -242,7 +237,7 @@ |
648 | anchors.right: parent.right |
649 | anchors.rightMargin: units.gu(1.5) |
650 | elide: Text.ElideRight |
651 | - text: album |
652 | + text: model.album |
653 | } |
654 | Label { |
655 | id: trackDuration |
656 | @@ -267,7 +262,7 @@ |
657 | fill: parent |
658 | } |
659 | listItem: search |
660 | - model: searchModel.model.get(index) |
661 | + model: songsSearchModel.get(index, songsSearchModel.RoleModelData) |
662 | row: Row { |
663 | AddToPlaylist { |
664 | |
665 | |
666 | === modified file 'MusicStart.qml' |
667 | --- MusicStart.qml 2014-06-02 15:51:48 +0000 |
668 | +++ MusicStart.qml 2014-06-19 01:49:30 +0000 |
669 | @@ -1,7 +1,8 @@ |
670 | /* |
671 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
672 | - * Daniel Holm <d.holmen@gmail.com> |
673 | - * Victor Thompson <victor.thompson@gmail.com> |
674 | + * Copyright (C) 2013, 2014 |
675 | + * Andrew Hayzen <ahayzen@gmail.com> |
676 | + * Daniel Holm <d.holmen@gmail.com> |
677 | + * Victor Thompson <victor.thompson@gmail.com> |
678 | * |
679 | * This program is free software; you can redistribute it and/or modify |
680 | * it under the terms of the GNU General Public License as published by |
681 | @@ -18,9 +19,12 @@ |
682 | |
683 | import QtQuick 2.0 |
684 | import Ubuntu.Components 0.1 |
685 | +import Ubuntu.Components 1.1 as Toolkit |
686 | import Ubuntu.Components.ListItems 0.1 |
687 | import Ubuntu.Components.Popups 0.1 |
688 | import Ubuntu.Components.ListItems 0.1 as ListItem |
689 | +import Ubuntu.MediaScanner 0.1 |
690 | +import Ubuntu.Thumbnailer 0.1 |
691 | import QtMultimedia 5.0 |
692 | import QtQuick.LocalStorage 2.0 |
693 | import "settings.js" as Settings |
694 | @@ -94,7 +98,7 @@ |
695 | model: recentModel.model |
696 | delegate: recentDelegate |
697 | header: Item { |
698 | - id: spacer |
699 | + id: recentSpacer |
700 | width: units.gu(1) |
701 | } |
702 | footer: Item { |
703 | @@ -121,7 +125,7 @@ |
704 | Item { |
705 | property string title: model.title |
706 | property string title2: model.title2 |
707 | - property var covers: type === "playlist" ? Playlists.getPlaylistCovers(title) : [Library.getAlbumCover(title)] |
708 | + property var covers: type === "playlist" ? Playlists.getPlaylistCovers(title) : [{author: model.title2, album: model.title}] |
709 | property string type: model.type |
710 | property string time: model.time |
711 | property string key: model.key |
712 | @@ -187,8 +191,9 @@ |
713 | if (type === "playlist") { |
714 | albumTracksModel.filterPlaylistTracks(key) |
715 | } else { |
716 | - albumTracksModel.filterAlbumTracks(title) |
717 | + songsSheet.album = title; |
718 | } |
719 | + songsSheet.genre = undefined; |
720 | |
721 | songsSheet.line1 = title2 |
722 | songsSheet.line2 = title |
723 | @@ -226,10 +231,13 @@ |
724 | anchors.topMargin: units.gu(1) |
725 | spacing: units.gu(1) |
726 | height: units.gu(18) |
727 | - model: genreModel.model |
728 | + model: GenresModel { |
729 | + store: musicStore |
730 | + } |
731 | + |
732 | delegate: genreDelegate |
733 | header: Item { |
734 | - id: spacer |
735 | + id: genreSpacer |
736 | width: units.gu(1) |
737 | } |
738 | orientation: ListView.Horizontal |
739 | @@ -237,19 +245,47 @@ |
740 | Component { |
741 | id: genreDelegate |
742 | Item { |
743 | - property string artist: model.artist |
744 | - property string album: model.album |
745 | - property string title: model.title |
746 | - property var covers: Library.getGenreCovers(model.genre) |
747 | - property string length: model.length |
748 | - property string file: model.file |
749 | - property string year: model.year |
750 | - property string genre: model.genre |
751 | - |
752 | id: genreItem |
753 | objectName: "genreItemObject" |
754 | height: genrelist.height - units.gu(1) |
755 | width: height |
756 | + |
757 | + Repeater { |
758 | + id: albumGenreModelRepeater |
759 | + model: AlbumsModel { |
760 | + genre: model.genre |
761 | + store: musicStore |
762 | + } |
763 | + |
764 | + delegate: Item { |
765 | + property string author: model.artist |
766 | + property string album: model.title |
767 | + } |
768 | + property var covers: [] |
769 | + signal finished() |
770 | + |
771 | + onFinished: { |
772 | + genreShape.count = count |
773 | + genreShape.covers = covers |
774 | + } |
775 | + onItemAdded: { |
776 | + covers.push({author: item.author, album: item.album}); |
777 | + |
778 | + if (index === count - 1) { |
779 | + finished(); |
780 | + } |
781 | + } |
782 | + } |
783 | + |
784 | + SongsModel { |
785 | + id: songGenreModel |
786 | + genre: model.genre |
787 | + // HACK: Temporarily setting limit to 500 to ensure model |
788 | + // is populated. See lp:1326753 |
789 | + limit: 500 |
790 | + store: musicStore |
791 | + } |
792 | + |
793 | CoverRow { |
794 | id: genreShape |
795 | anchors { |
796 | @@ -257,19 +293,20 @@ |
797 | left: parent.left |
798 | verticalCenter: parent.verticalCenter |
799 | } |
800 | - count: genreItem.covers.length |
801 | + count: 0 |
802 | size: genreItem.width |
803 | - covers: genreItem.covers |
804 | + covers: [] |
805 | spacing: units.gu(2) |
806 | } |
807 | MouseArea { |
808 | anchors.fill: parent |
809 | onClicked: { |
810 | - albumTracksModel.filterGenreTracks(genre) |
811 | + songsSheet.album = undefined |
812 | + songsSheet.genre = model.genre |
813 | songsSheet.line1 = "Genre" |
814 | - songsSheet.line2 = genre |
815 | - songsSheet.isAlbum = false |
816 | - songsSheet.covers = covers |
817 | + songsSheet.line2 = model.genre |
818 | + songsSheet.isAlbum = true |
819 | + songsSheet.covers = genreShape.covers |
820 | PopupUtils.open(songsSheet.sheet) |
821 | } |
822 | } |
823 | @@ -298,7 +335,7 @@ |
824 | anchors.rightMargin: units.gu(1) |
825 | color: styleMusic.common.white |
826 | elide: Text.ElideRight |
827 | - text: genre |
828 | + text: model.genre |
829 | fontSize: "small" |
830 | } |
831 | Label { |
832 | @@ -311,7 +348,7 @@ |
833 | anchors.rightMargin: units.gu(1) |
834 | color: styleMusic.nowPlaying.labelSecondaryColor |
835 | elide: Text.ElideRight |
836 | - text: i18n.tr("%1 song", "%1 songs", model.total).arg(model.total) |
837 | + text: i18n.tr("%1 song", "%1 songs", songGenreModel.rowCount).arg(songGenreModel.rowCount) |
838 | fontSize: "x-small" |
839 | } |
840 | } |
841 | @@ -343,7 +380,16 @@ |
842 | anchors.topMargin: units.gu(1) |
843 | spacing: units.gu(1) |
844 | height: units.gu(18) |
845 | - model: albumModel.model |
846 | + model: Toolkit.SortFilterModel { |
847 | + id: albumsModelFilter |
848 | + property alias rowCount: albumsModel.rowCount |
849 | + model: AlbumsModel { |
850 | + id: albumsModel |
851 | + store: musicStore |
852 | + } |
853 | + sort.property: "title" |
854 | + sort.order: Qt.AscendingOrder |
855 | + } |
856 | delegate: albumDelegate |
857 | header: Item { |
858 | id: albumSpacer |
859 | @@ -355,12 +401,8 @@ |
860 | id: albumDelegate |
861 | Item { |
862 | property string artist: model.artist |
863 | - property string album: model.album |
864 | - property var covers: [Library.getAlbumCover(album)] |
865 | - property string length: model.length |
866 | - property string file: model.file |
867 | - property string year: model.year |
868 | - property string genre: model.genre |
869 | + property string album: model.title |
870 | + property var covers: [{author: model.artist, album: model.title}] |
871 | |
872 | id: albumItem |
873 | objectName: "albumItemObject" |
874 | @@ -381,7 +423,8 @@ |
875 | MouseArea { |
876 | anchors.fill: parent |
877 | onClicked: { |
878 | - albumTracksModel.filterAlbumTracks(album) |
879 | + songsSheet.album = album; |
880 | + songsSheet.genre = undefined |
881 | songsSheet.line1 = artist |
882 | songsSheet.line2 = album |
883 | songsSheet.isAlbum = true |
884 | |
885 | === modified file 'MusicToolbar.qml' |
886 | --- MusicToolbar.qml 2014-05-04 05:30:54 +0000 |
887 | +++ MusicToolbar.qml 2014-06-19 01:49:30 +0000 |
888 | @@ -1,7 +1,8 @@ |
889 | /* |
890 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
891 | - * Daniel Holm <d.holmen@gmail.com> |
892 | - * Victor Thompson <victor.thompson@gmail.com> |
893 | + * Copyright (C) 2013, 2014 |
894 | + * Andrew Hayzen <ahayzen@gmail.com> |
895 | + * Daniel Holm <d.holmen@gmail.com> |
896 | + * Victor Thompson <victor.thompson@gmail.com> |
897 | * |
898 | * This program is free software; you can redistribute it and/or modify |
899 | * it under the terms of the GNU General Public License as published by |
900 | @@ -21,7 +22,6 @@ |
901 | import QtMultimedia 5.0 |
902 | import Ubuntu.Components 0.1 |
903 | import Ubuntu.Components.Popups 0.1 |
904 | -import "meta-database.js" as Library |
905 | import "settings.js" as Settings |
906 | |
907 | Item { |
908 | |
909 | === modified file 'MusicTracks.qml' |
910 | --- MusicTracks.qml 2014-04-26 17:13:02 +0000 |
911 | +++ MusicTracks.qml 2014-06-19 01:49:30 +0000 |
912 | @@ -1,6 +1,8 @@ |
913 | /* |
914 | - * Copyright (C) 2013 Victor Thompson <victor.thompson@gmail.com> |
915 | - * Daniel Holm <d.holmen@gmail.com> |
916 | + * Copyright (C) 2013, 2014 |
917 | + * Andrew Hayzen <ahayzen@gmail.com> |
918 | + * Daniel Holm <d.holmen@gmail.com> |
919 | + * Victor Thompson <victor.thompson@gmail.com> |
920 | * |
921 | * This program is free software; you can redistribute it and/or modify |
922 | * it under the terms of the GNU General Public License as published by |
923 | @@ -17,12 +19,14 @@ |
924 | |
925 | import QtQuick 2.0 |
926 | import Ubuntu.Components 0.1 |
927 | +import Ubuntu.Components 1.1 as Toolkit |
928 | import Ubuntu.Components.ListItems 0.1 |
929 | import Ubuntu.Components.ListItems 0.1 as ListItem |
930 | +import Ubuntu.MediaScanner 0.1 |
931 | +import Ubuntu.Thumbnailer 0.1 |
932 | import QtMultimedia 5.0 |
933 | import QtQuick.LocalStorage 2.0 |
934 | import "settings.js" as Settings |
935 | -import "meta-database.js" as Library |
936 | import "playlists.js" as Playlists |
937 | import "common" |
938 | import "common/ExpanderItems" |
939 | @@ -43,23 +47,30 @@ |
940 | } |
941 | } |
942 | |
943 | + |
944 | ListView { |
945 | id: tracklist |
946 | anchors.fill: parent |
947 | anchors.bottomMargin: musicToolbar.mouseAreaOffset + musicToolbar.minimizedHeight |
948 | highlightFollowsCurrentItem: false |
949 | - model: libraryModel.model |
950 | + model: Toolkit.SortFilterModel { |
951 | + id: songsModelFilter |
952 | + property alias rowCount: songsModel.rowCount |
953 | + model: SongsModel { |
954 | + id: songsModel |
955 | + // HACK: Temporarily setting limit to 500 to ensure model |
956 | + // is populated. See lp:1326753 |
957 | + limit: 500 |
958 | + store: musicStore |
959 | + } |
960 | + sort.property: "title" |
961 | + sort.order: Qt.AscendingOrder |
962 | + } |
963 | delegate: trackDelegate |
964 | Component { |
965 | id: trackDelegate |
966 | ListItem.Standard { |
967 | id: track |
968 | - property string artist: model.artist |
969 | - property string album: model.album |
970 | - property string title: model.title |
971 | - property string cover: model.cover |
972 | - property string length: model.length |
973 | - property string file: model.file |
974 | width: parent.width |
975 | height: styleMusic.common.itemHeight |
976 | |
977 | @@ -70,7 +81,7 @@ |
978 | focus = true |
979 | } |
980 | |
981 | - trackClicked(libraryModel, index) // play track |
982 | + trackClicked(tracklist.model, index) // play track |
983 | } |
984 | } |
985 | |
986 | @@ -90,7 +101,7 @@ |
987 | width: styleMusic.common.albumSize |
988 | height: styleMusic.common.albumSize |
989 | image: Image { |
990 | - source: cover !== "" ? cover : Qt.resolvedUrl("images/music-app-cover@30.png") |
991 | + source: "image://albumart/artist=" + model.author + "&album=" + model.album |
992 | onStatusChanged: { |
993 | if (status === Image.Error) { |
994 | source = Qt.resolvedUrl("images/music-app-cover@30.png") |
995 | @@ -111,7 +122,7 @@ |
996 | anchors.right: parent.right |
997 | anchors.rightMargin: units.gu(1.5) |
998 | elide: Text.ElideRight |
999 | - text: artist |
1000 | + text: model.author |
1001 | } |
1002 | Label { |
1003 | id: trackTitle |
1004 | @@ -127,7 +138,7 @@ |
1005 | anchors.right: parent.right |
1006 | anchors.rightMargin: units.gu(1.5) |
1007 | elide: Text.ElideRight |
1008 | - text: track.title |
1009 | + text: model.title |
1010 | } |
1011 | Label { |
1012 | id: trackAlbum |
1013 | @@ -142,7 +153,7 @@ |
1014 | anchors.right: parent.right |
1015 | anchors.rightMargin: units.gu(1.5) |
1016 | elide: Text.ElideRight |
1017 | - text: album |
1018 | + text: model.album |
1019 | } |
1020 | Label { |
1021 | id: trackDuration |
1022 | @@ -157,7 +168,7 @@ |
1023 | anchors.rightMargin: units.gu(1.5) |
1024 | elide: Text.ElideRight |
1025 | visible: false |
1026 | - text: "" |
1027 | + text: "" // model.duration |
1028 | } |
1029 | } |
1030 | |
1031 | @@ -167,7 +178,7 @@ |
1032 | fill: parent |
1033 | } |
1034 | listItem: track |
1035 | - model: libraryModel.model.get(index) |
1036 | + model: songsModelFilter.get(index, songsModelFilter.RoleModelData) |
1037 | row: Row { |
1038 | AddToPlaylist { |
1039 | |
1040 | |
1041 | === modified file 'MusicaddtoPlaylist.qml' |
1042 | --- MusicaddtoPlaylist.qml 2014-04-26 17:13:02 +0000 |
1043 | +++ MusicaddtoPlaylist.qml 2014-06-19 01:49:30 +0000 |
1044 | @@ -1,7 +1,8 @@ |
1045 | /* |
1046 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1047 | - * Daniel Holm <d.holmen@gmail.com> |
1048 | - * Victor Thompson <victor.thompson@gmail.com> |
1049 | + * Copyright (C) 2013, 2014 |
1050 | + * Andrew Hayzen <ahayzen@gmail.com> |
1051 | + * Daniel Holm <d.holmen@gmail.com> |
1052 | + * Victor Thompson <victor.thompson@gmail.com> |
1053 | * |
1054 | * This program is free software; you can redistribute it and/or modify |
1055 | * it under the terms of the GNU General Public License as published by |
1056 | @@ -78,13 +79,13 @@ |
1057 | property string name: model.name |
1058 | property string count: model.count |
1059 | onClicked: { |
1060 | - console.debug("Debug: "+chosenElement.file+" added to "+name) |
1061 | + console.debug("Debug: "+chosenElement.filename+" added to "+name) |
1062 | Playlists.addtoPlaylist(name, |
1063 | - chosenElement.file, |
1064 | - chosenElement.artist, |
1065 | + chosenElement.filename, |
1066 | + chosenElement.author, |
1067 | chosenElement.title, |
1068 | chosenElement.album, |
1069 | - chosenElement.cover, |
1070 | + chosenElement.art, |
1071 | "","","","") |
1072 | count = Playlists.getPlaylistCount(name) // get the new count |
1073 | playlistModel.model.set(index, {"count": count}) // update number ot tracks in playlist |
1074 | |
1075 | === modified file 'Player.qml' |
1076 | --- Player.qml 2014-04-16 11:58:54 +0000 |
1077 | +++ Player.qml 2014-06-19 01:49:30 +0000 |
1078 | @@ -1,7 +1,8 @@ |
1079 | /* |
1080 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1081 | - * Daniel Holm <d.holmen@gmail.com> |
1082 | - * Victor Thompson <victor.thompson@gmail.com> |
1083 | + * Copyright (C) 2013, 2014 |
1084 | + * Andrew Hayzen <ahayzen@gmail.com> |
1085 | + * Daniel Holm <d.holmen@gmail.com> |
1086 | + * Victor Thompson <victor.thompson@gmail.com> |
1087 | * |
1088 | * This program is free software; you can redistribute it and/or modify |
1089 | * it under the terms of the GNU General Public License as published by |
1090 | @@ -33,7 +34,6 @@ |
1091 | |
1092 | property string currentMetaAlbum: "" |
1093 | property string currentMetaArtist: "" |
1094 | - property string currentMetaCover: "" |
1095 | property string currentMetaFile: "" |
1096 | property string currentMetaTitle: "" |
1097 | property int currentIndex: -1 |
1098 | @@ -61,9 +61,9 @@ |
1099 | onCountChanged: { |
1100 | if (trackQueue.model.count === 1) { |
1101 | player.currentIndex = 0; |
1102 | - player.source = Qt.resolvedUrl(trackQueue.model.get(0).file) |
1103 | + player.source = Qt.resolvedUrl(trackQueue.model.get(0).filename) |
1104 | } else if (trackQueue.model.count === 0) { |
1105 | - player.currentMetaCover = "" |
1106 | + currentMetaFile = "" |
1107 | } |
1108 | } |
1109 | } |
1110 | @@ -117,11 +117,11 @@ |
1111 | } |
1112 | |
1113 | if (startPlaying) { // only start the track if told |
1114 | - playSong(trackQueue.model.get(newIndex).file, newIndex) |
1115 | + playSong(trackQueue.model.get(newIndex).filename, newIndex) |
1116 | } |
1117 | else { |
1118 | currentIndex = newIndex |
1119 | - source = Qt.resolvedUrl(trackQueue.model.get(newIndex).file) |
1120 | + source = Qt.resolvedUrl(trackQueue.model.get(newIndex).filename) |
1121 | } |
1122 | } |
1123 | |
1124 | @@ -183,9 +183,8 @@ |
1125 | else { |
1126 | var obj = trackQueue.model.get(player.currentIndex); |
1127 | currentMetaAlbum = obj.album; |
1128 | - currentMetaArtist = obj.artist; |
1129 | - currentMetaCover = obj.cover; |
1130 | - currentMetaFile = obj.file; |
1131 | + currentMetaArtist = obj.author; |
1132 | + currentMetaFile = obj.filename; |
1133 | currentMetaTitle = obj.title; |
1134 | } |
1135 | |
1136 | |
1137 | === modified file 'Style.qml' |
1138 | --- Style.qml 2014-04-25 17:05:03 +0000 |
1139 | +++ Style.qml 2014-06-19 01:49:30 +0000 |
1140 | @@ -1,7 +1,8 @@ |
1141 | /* |
1142 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1143 | - * Daniel Holm <d.holmen@gmail.com> |
1144 | - * Victor Thompson <victor.thompson@gmail.com> |
1145 | + * Copyright (C) 2013, 2014 |
1146 | + * Andrew Hayzen <ahayzen@gmail.com> |
1147 | + * Daniel Holm <d.holmen@gmail.com> |
1148 | + * Victor Thompson <victor.thompson@gmail.com> |
1149 | * |
1150 | * This program is free software; you can redistribute it and/or modify |
1151 | * it under the terms of the GNU General Public License as published by |
1152 | |
1153 | === modified file 'click/apparmor.json' |
1154 | --- click/apparmor.json 2014-05-30 14:23:43 +0000 |
1155 | +++ click/apparmor.json 2014-06-19 01:49:30 +0000 |
1156 | @@ -1,5 +1,5 @@ |
1157 | { |
1158 | - "policy_version": 1.1, |
1159 | + "policy_version": 1.2, |
1160 | "template": "unconfined", |
1161 | "policy_groups": [] |
1162 | } |
1163 | |
1164 | === modified file 'click/manifest.json.in' |
1165 | --- click/manifest.json.in 2014-06-06 11:35:53 +0000 |
1166 | +++ click/manifest.json.in 2014-06-19 01:49:30 +0000 |
1167 | @@ -1,7 +1,6 @@ |
1168 | { |
1169 | - "description": "A music application for Ubuntu", |
1170 | - "framework": "ubuntu-sdk-14.04-dev1", |
1171 | - "architecture": "armhf", |
1172 | + "description": "A music application for ubuntu", |
1173 | + "framework": "ubuntu-sdk-14.10-qml-dev1", |
1174 | "hooks": { |
1175 | "@APP_NAME@": { |
1176 | "apparmor": "apparmor.json", |
1177 | |
1178 | === modified file 'common/AlbumsSheet.qml' |
1179 | --- common/AlbumsSheet.qml 2014-05-19 23:13:39 +0000 |
1180 | +++ common/AlbumsSheet.qml 2014-06-19 01:49:30 +0000 |
1181 | @@ -1,7 +1,8 @@ |
1182 | /* |
1183 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1184 | - * Daniel Holm <d.holmen@gmail.com> |
1185 | - * Victor Thompson <victor.thompson@gmail.com> |
1186 | + * Copyright (C) 2013, 2014 |
1187 | + * Andrew Hayzen <ahayzen@gmail.com> |
1188 | + * Daniel Holm <d.holmen@gmail.com> |
1189 | + * Victor Thompson <victor.thompson@gmail.com> |
1190 | * |
1191 | * This program is free software; you can redistribute it and/or modify |
1192 | * it under the terms of the GNU General Public License as published by |
1193 | @@ -21,6 +22,8 @@ |
1194 | import Ubuntu.Components.ListItems 0.1 |
1195 | import Ubuntu.Components.Popups 0.1 |
1196 | import Ubuntu.Components.ListItems 0.1 as ListItem |
1197 | +import Ubuntu.MediaScanner 0.1 |
1198 | +import Ubuntu.Thumbnailer 0.1 |
1199 | import QtQuick.LocalStorage 2.0 |
1200 | import "../meta-database.js" as Library |
1201 | |
1202 | @@ -58,7 +61,12 @@ |
1203 | width: parent.width |
1204 | anchors.top: parent.top |
1205 | anchors.bottom: parent.bottom |
1206 | - model: artistAlbumsModel.model |
1207 | + model: AlbumsModel { |
1208 | + id: artistsModel |
1209 | + albumArtist: sheetItem.artist |
1210 | + store: musicStore |
1211 | + } |
1212 | + |
1213 | delegate: albumTracksDelegate |
1214 | header: artistHeaderDelegate |
1215 | |
1216 | @@ -132,6 +140,15 @@ |
1217 | fontSize: "large" |
1218 | } |
1219 | |
1220 | + SongsModel { |
1221 | + id: songArtistModel |
1222 | + albumArtist: sheetItem.artist |
1223 | + // HACK: Temporarily setting limit to 500 to ensure model |
1224 | + // is populated. See lp:1326753 |
1225 | + limit: 500 |
1226 | + store: musicStore |
1227 | + } |
1228 | + |
1229 | // Play |
1230 | Rectangle { |
1231 | id: playRow |
1232 | @@ -167,10 +184,7 @@ |
1233 | MouseArea { |
1234 | anchors.fill: parent |
1235 | onClicked: { |
1236 | - albumTracksModel.filterArtistTracks(artist) |
1237 | - trackQueue.model.clear() |
1238 | - addQueueFromModel(albumTracksModel) |
1239 | - trackClicked(trackQueue, 0) // play track |
1240 | + trackClicked(songArtistModel, 0, true) |
1241 | |
1242 | // TODO: add links to recent |
1243 | |
1244 | @@ -218,8 +232,7 @@ |
1245 | MouseArea { |
1246 | anchors.fill: parent |
1247 | onClicked: { |
1248 | - albumTracksModel.filterArtistTracks(artist) |
1249 | - addQueueFromModel(albumTracksModel) |
1250 | + addQueueFromModel(songArtistModel) |
1251 | } |
1252 | } |
1253 | } |
1254 | @@ -236,6 +249,23 @@ |
1255 | width: parent.width |
1256 | height: units.gu(20) |
1257 | |
1258 | + SongsModel { |
1259 | + id: songAlbumArtistModel |
1260 | + albumArtist: model.artist |
1261 | + album: model.title |
1262 | + // HACK: Temporarily setting limit to 500 to ensure model |
1263 | + // is populated. See lp:1326753 |
1264 | + limit: 500 |
1265 | + store: musicStore |
1266 | + } |
1267 | + Repeater { |
1268 | + id: songAlbumArtistModelRepeater |
1269 | + model: songAlbumArtistModel |
1270 | + delegate: Text { text: new Date(model.date).toLocaleString(Qt.locale(),'yyyy'); visible: false } |
1271 | + property string year: "" |
1272 | + onItemAdded: year = item.text |
1273 | + } |
1274 | + |
1275 | CoverRow { |
1276 | id: albumImage |
1277 | anchors { |
1278 | @@ -246,7 +276,7 @@ |
1279 | } |
1280 | count: 1 |
1281 | size: parent.height |
1282 | - covers: [Library.getAlbumCover(model.album)] |
1283 | + covers: [{author: artist, album: model.title}] |
1284 | objectName: "artistsheet-albumcover" |
1285 | spacing: units.gu(2) |
1286 | |
1287 | @@ -259,13 +289,12 @@ |
1288 | focus = true |
1289 | } |
1290 | |
1291 | - albumTracksModel.filterAlbumTracks(album) |
1292 | + albumSheet.album = model.title; |
1293 | + |
1294 | albumSheet.line1 = artist |
1295 | - albumSheet.line2 = model.album |
1296 | + albumSheet.line2 = model.title |
1297 | albumSheet.isAlbum = true |
1298 | - albumSheet.file = file |
1299 | - albumSheet.year = year |
1300 | - albumSheet.covers = [Library.getAlbumCover(model.album) || Qt.resolvedUrl("../images/music-app-cover@30.png")] |
1301 | + albumSheet.covers = [{author: artist, album: model.title}] |
1302 | PopupUtils.open(albumSheet.sheet) |
1303 | |
1304 | // TODO: This closes the SDK defined sheet |
1305 | @@ -305,7 +334,7 @@ |
1306 | anchors.right: parent.right |
1307 | anchors.rightMargin: units.gu(1.5) |
1308 | elide: Text.ElideRight |
1309 | - text: album |
1310 | + text: model.title |
1311 | } |
1312 | Label { |
1313 | id: albumYear |
1314 | @@ -320,7 +349,9 @@ |
1315 | anchors.right: parent.right |
1316 | anchors.rightMargin: units.gu(1.5) |
1317 | elide: Text.ElideRight |
1318 | - text: i18n.tr(model.year + " | %1 song", model.year + " | %1 songs", Library.getAlbumTracks(album).length).arg(Library.getAlbumTracks(album).length) |
1319 | + text: i18n.tr(songAlbumArtistModelRepeater.year + " | %1 song", |
1320 | + songAlbumArtistModelRepeater.year + " | %1 songs", |
1321 | + songAlbumArtistModelRepeater.count).arg(songAlbumArtistModelRepeater.count) |
1322 | } |
1323 | |
1324 | // Play |
1325 | @@ -355,13 +386,10 @@ |
1326 | MouseArea { |
1327 | anchors.fill: parent |
1328 | onClicked: { |
1329 | - albumTracksModel.filterAlbumTracks(album) |
1330 | - Library.addRecent(album, artist, Library.getAlbumCover(album), album, "album") |
1331 | + Library.addRecent(model.title, artist, "", model.title, "album") |
1332 | mainView.hasRecent = true |
1333 | recentModel.filterRecent() |
1334 | - trackQueue.model.clear() |
1335 | - addQueueFromModel(albumTracksModel) |
1336 | - trackClicked(trackQueue, 0) // play track |
1337 | + trackClicked(songAlbumArtistModel, 0, true) |
1338 | |
1339 | // TODO: This closes the SDK defined sheet |
1340 | // component. It should be able to close |
1341 | @@ -403,8 +431,7 @@ |
1342 | MouseArea { |
1343 | anchors.fill: parent |
1344 | onClicked: { |
1345 | - albumTracksModel.filterAlbumTracks(album) |
1346 | - addQueueFromModel(albumTracksModel) |
1347 | + addQueueFromModel(songAlbumArtistModel) |
1348 | } |
1349 | } |
1350 | } |
1351 | |
1352 | === modified file 'common/BlurredBackground.qml' |
1353 | --- common/BlurredBackground.qml 2014-04-12 01:06:28 +0000 |
1354 | +++ common/BlurredBackground.qml 2014-06-19 01:49:30 +0000 |
1355 | @@ -1,7 +1,8 @@ |
1356 | /* |
1357 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1358 | - * Daniel Holm <d.holmen@gmail.com> |
1359 | - * Victor Thompson <victor.thompson@gmail.com> |
1360 | + * Copyright (C) 2013, 2014 |
1361 | + * Andrew Hayzen <ahayzen@gmail.com> |
1362 | + * Daniel Holm <d.holmen@gmail.com> |
1363 | + * Victor Thompson <victor.thompson@gmail.com> |
1364 | * |
1365 | * This program is free software; you can redistribute it and/or modify |
1366 | * it under the terms of the GNU General Public License as published by |
1367 | @@ -23,15 +24,14 @@ |
1368 | // Blurred background |
1369 | Rectangle { |
1370 | anchors.fill: parent |
1371 | - property string cover: player.currentMetaCover !== "" ? |
1372 | - player.currentMetaCover : |
1373 | - "../images/music-app-cover@30.png" |
1374 | + property string art: player.currentMetaFile === "" ? Qt.resolvedUrl("../images/music-app-cover@30.png") : "image://albumart/artist=" + player.currentMetaArtist + "&album=" + player.currentMetaAlbum |
1375 | + |
1376 | // the album art |
1377 | Image { |
1378 | id: backgroundImage |
1379 | anchors.horizontalCenter: parent.horizontalCenter |
1380 | anchors.verticalCenter: parent.verticalCenter |
1381 | - source: cover // this has to be fixed for the default cover art to work - cant find in this dir |
1382 | + source: art // this has to be fixed for the default cover art to work - cant find in this dir |
1383 | height: Math.max(parent.height, parent.width) |
1384 | width: Math.max(parent.height, parent.width) |
1385 | visible: false |
1386 | @@ -54,10 +54,10 @@ |
1387 | color: "white" |
1388 | opacity: 0.7 |
1389 | } |
1390 | - onCoverChanged: { |
1391 | + onArtChanged: { |
1392 | // TODO: This is a work around for LP:1261078 and LP:1306845. Ideally, |
1393 | // there should be a better way of getting the blur to repaint |
1394 | - backgroundImage.source = cover |
1395 | + backgroundImage.source = art |
1396 | backgroundBlur.source = null |
1397 | backgroundBlur.source = backgroundImage |
1398 | } |
1399 | |
1400 | === modified file 'common/CoverRow.qml' |
1401 | --- common/CoverRow.qml 2014-04-11 18:18:12 +0000 |
1402 | +++ common/CoverRow.qml 2014-06-19 01:49:30 +0000 |
1403 | @@ -1,5 +1,8 @@ |
1404 | /* |
1405 | - * Copyright (C) 2013 Nekhelesh Ramananthan <krnekhelesh@gmail.com> |
1406 | + * Copyright (C) 2013, 2014 |
1407 | + * Andrew Hayzen <ahayzen@gmail.com> |
1408 | + * Nekhelesh Ramananthan <krnekhelesh@gmail.com> |
1409 | + * Victor Thompson <victor.thompson@gmail.com> |
1410 | * |
1411 | * This program is free software; you can redistribute it and/or modify |
1412 | * it under the terms of the GNU General Public License as published by |
1413 | @@ -52,8 +55,9 @@ |
1414 | delegate: Image { |
1415 | width: coverRow.size |
1416 | height: width |
1417 | - source: coverRow.count === 0 || coverRow.covers[index] === "" |
1418 | - ? Qt.resolvedUrl("../images/music-app-cover@30.png") : coverRow.covers[index] |
1419 | + source: coverRow.count !== 0 && coverRow.covers[index] !== "" && coverRow.covers[index] !== undefined |
1420 | + ? "image://albumart/artist=" + coverRow.covers[index].author + "&album=" + coverRow.covers[index].album |
1421 | + : Qt.resolvedUrl("../images/music-app-cover@30.png") |
1422 | onStatusChanged: { |
1423 | if (status === Image.Error) { |
1424 | source = Qt.resolvedUrl("../images/music-app-cover@30.png") |
1425 | |
1426 | === modified file 'common/Expander.qml' |
1427 | --- common/Expander.qml 2014-04-30 01:59:41 +0000 |
1428 | +++ common/Expander.qml 2014-06-19 01:49:30 +0000 |
1429 | @@ -1,7 +1,8 @@ |
1430 | /* |
1431 | - * Copyright (C) 2014 Andrew Hayzen <ahayzen@gmail.com> |
1432 | - * Daniel Holm <d.holmen@gmail.com> |
1433 | - * Victor Thompson <victor.thompson@gmail.com> |
1434 | + * Copyright (C) 2013, 2014 |
1435 | + * Andrew Hayzen <ahayzen@gmail.com> |
1436 | + * Daniel Holm <d.holmen@gmail.com> |
1437 | + * Victor Thompson <victor.thompson@gmail.com> |
1438 | * |
1439 | * This program is free software; you can redistribute it and/or modify |
1440 | * it under the terms of the GNU General Public License as published by |
1441 | |
1442 | === modified file 'common/SongsSheet.qml' |
1443 | --- common/SongsSheet.qml 2014-04-26 17:13:02 +0000 |
1444 | +++ common/SongsSheet.qml 2014-06-19 01:49:30 +0000 |
1445 | @@ -1,7 +1,8 @@ |
1446 | /* |
1447 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
1448 | - * Daniel Holm <d.holmen@gmail.com> |
1449 | - * Victor Thompson <victor.thompson@gmail.com> |
1450 | + * Copyright (C) 2013, 2014 |
1451 | + * Andrew Hayzen <ahayzen@gmail.com> |
1452 | + * Daniel Holm <d.holmen@gmail.com> |
1453 | + * Victor Thompson <victor.thompson@gmail.com> |
1454 | * |
1455 | * This program is free software; you can redistribute it and/or modify |
1456 | * it under the terms of the GNU General Public License as published by |
1457 | @@ -21,6 +22,8 @@ |
1458 | import Ubuntu.Components.ListItems 0.1 |
1459 | import Ubuntu.Components.Popups 0.1 |
1460 | import Ubuntu.Components.ListItems 0.1 as ListItem |
1461 | +import Ubuntu.MediaScanner 0.1 |
1462 | +import Ubuntu.Thumbnailer 0.1 |
1463 | import QtQuick.LocalStorage 2.0 |
1464 | import "../meta-database.js" as Library |
1465 | import "ExpanderItems" |
1466 | @@ -38,6 +41,17 @@ |
1467 | property bool isAlbum: false |
1468 | property alias sheet: sheetComponent |
1469 | |
1470 | + property alias album: songsModel.album |
1471 | + property alias genre: songsModel.genre |
1472 | + |
1473 | + SongsModel { |
1474 | + id: songsModel |
1475 | + // HACK: Temporarily setting limit to 500 to ensure model |
1476 | + // is populated. See lp:1326753 |
1477 | + limit: 500 |
1478 | + store: musicStore |
1479 | + } |
1480 | + |
1481 | Component { |
1482 | id: sheetComponent |
1483 | DefaultSheet { |
1484 | @@ -61,7 +75,8 @@ |
1485 | width: parent.width |
1486 | anchors.top: parent.top |
1487 | anchors.bottom: parent.bottom |
1488 | - model: albumTracksModel.model |
1489 | + model: isAlbum ? songsModel : albumTracksModel.model |
1490 | + |
1491 | delegate: albumTracksDelegate |
1492 | header: ListItem.Standard { |
1493 | id: albumInfo |
1494 | @@ -125,8 +140,8 @@ |
1495 | anchors.right: parent.right |
1496 | anchors.rightMargin: units.gu(1.5) |
1497 | elide: Text.ElideRight |
1498 | - text: isAlbum ? i18n.tr(year + " | %1 song", year + " | %1 songs", albumTracksModel.model.count).arg(albumTracksModel.model.count) |
1499 | - : i18n.tr("%1 song", "%1 songs", albumTracksModel.model.count).arg(albumTracksModel.model.count) |
1500 | + text: isAlbum ? i18n.tr(year + " | %1 song", year + " | %1 songs", albumtrackslist.count).arg(albumtrackslist.count) |
1501 | + : i18n.tr("%1 song", "%1 songs", albumtrackslist.count).arg(albumtrackslist.count) |
1502 | |
1503 | } |
1504 | |
1505 | @@ -162,13 +177,14 @@ |
1506 | MouseArea { |
1507 | anchors.fill: parent |
1508 | onClicked: { |
1509 | - trackClicked(albumTracksModel, 0) // play track |
1510 | - if (isAlbum) { |
1511 | - Library.addRecent(sheetItem.line2, sheetItem.line1, sheetItem.cover, sheetItem.line2, "album") |
1512 | + trackClicked(albumtrackslist.model, 0) // play track |
1513 | + |
1514 | + if (isAlbum && sheetItem.line1 != "Genre") { |
1515 | + Library.addRecent(sheetItem.line2, sheetItem.line1, sheetItem.covers[0], sheetItem.line2, "album") |
1516 | mainView.hasRecent = true |
1517 | recentModel.filterRecent() |
1518 | } else if (sheetItem.line1 == "Playlist") { |
1519 | - Library.addRecent(sheetItem.line2, "Playlist", sheetItem.cover, sheetItem.line2, "playlist") |
1520 | + Library.addRecent(sheetItem.line2, "Playlist", sheetItem.covers[0], sheetItem.line2, "playlist") |
1521 | mainView.hasRecent = true |
1522 | recentModel.filterRecent() |
1523 | } |
1524 | @@ -213,7 +229,7 @@ |
1525 | MouseArea { |
1526 | anchors.fill: parent |
1527 | onClicked: { |
1528 | - addQueueFromModel(albumTracksModel) |
1529 | + addQueueFromModel(albumtrackslist.model) |
1530 | } |
1531 | } |
1532 | } |
1533 | @@ -237,13 +253,13 @@ |
1534 | if (focus == false) { |
1535 | focus = true |
1536 | } |
1537 | - trackClicked(albumTracksModel, index) // play track |
1538 | - if (isAlbum) { |
1539 | - Library.addRecent(sheetItem.line2, sheetItem.line1, sheetItem.cover, sheetItem.line2, "album") |
1540 | + trackClicked(albumtrackslist.model, index) // play track |
1541 | + if (isAlbum && sheetItem.line1 != "Genre") { |
1542 | + Library.addRecent(sheetItem.line2, sheetItem.line1, sheetItem.covers[0], sheetItem.line2, "album") |
1543 | mainView.hasRecent = true |
1544 | recentModel.filterRecent() |
1545 | } else if (sheetItem.line1 == "Playlist") { |
1546 | - Library.addRecent(sheetItem.line2, "Playlist", sheetItem.cover, sheetItem.line2, "playlist") |
1547 | + Library.addRecent(sheetItem.line2, "Playlist", sheetItem.covers[0], sheetItem.line2, "playlist") |
1548 | mainView.hasRecent = true |
1549 | recentModel.filterRecent() |
1550 | } |
1551 | @@ -275,7 +291,7 @@ |
1552 | height: styleMusic.common.albumSize |
1553 | visible: !isAlbum |
1554 | image: Image { |
1555 | - source: model.cover !== "" ? model.cover : Qt.resolvedUrl("../images/music-app-cover@30.png") |
1556 | + source: "image://albumart/artist=" + model.author + "&album=" + model.album |
1557 | onStatusChanged: { |
1558 | if (status === Image.Error) { |
1559 | source = Qt.resolvedUrl("../images/music-app-cover@30.png") |
1560 | @@ -300,7 +316,7 @@ |
1561 | rightMargin: units.gu(1.5) |
1562 | } |
1563 | elide: Text.ElideRight |
1564 | - text: model.artist |
1565 | + text: model.author |
1566 | } |
1567 | |
1568 | Label { |
1569 | @@ -348,7 +364,7 @@ |
1570 | fill: parent |
1571 | } |
1572 | listItem: track |
1573 | - model: albumTracksModel.model.get(index) |
1574 | + model: isAlbum ? albumtrackslist.model.get(index, albumTracksModel.model.RoleModelData) : albumtrackslist.model.get(index) |
1575 | row: Row { |
1576 | AddToPlaylist { |
1577 | |
1578 | @@ -360,10 +376,10 @@ |
1579 | } |
1580 | |
1581 | Component.onCompleted: { |
1582 | - if (index === 0) |
1583 | + if (model.date !== undefined && sheetItem.year === "") |
1584 | { |
1585 | - sheetItem.file = model.file; |
1586 | - sheetItem.year = model.year; |
1587 | + sheetItem.file = model.filename; |
1588 | + sheetItem.year = new Date(model.date).toLocaleString(Qt.locale(),'yyyy'); |
1589 | } |
1590 | } |
1591 | } |
1592 | |
1593 | === modified file 'debian/control' |
1594 | --- debian/control 2014-06-06 11:35:53 +0000 |
1595 | +++ debian/control 2014-06-19 01:49:30 +0000 |
1596 | @@ -13,18 +13,21 @@ |
1597 | |
1598 | Package: music-app |
1599 | Architecture: all |
1600 | -Depends: grilo-plugins-0.2-mediascanner, |
1601 | - mediascanner, |
1602 | +Depends: mediascanner2.0, |
1603 | + gstreamer0.10-fluendo-mp3, |
1604 | + gstreamer1.0-fluendo-mp3, |
1605 | qmlscene, |
1606 | qtdeclarative5-localstorage-plugin, |
1607 | qtdeclarative5-particles-plugin, |
1608 | - qtdeclarative5-qtgrilo0.1, |
1609 | qtdeclarative5-qtmultimedia-plugin, |
1610 | qtdeclarative5-qtquick2-plugin, |
1611 | + qtdeclarative5-ubuntu-mediascanner0.1, |
1612 | + qtdeclarative5-ubuntu-thumbnailer0.1, |
1613 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
1614 | qtdeclarative5-usermetrics0.1, |
1615 | qtdeclarative5-window-plugin, |
1616 | qtdeclarative5-xmllistmodel-plugin, |
1617 | + thumbnailer-service, |
1618 | suru-icon-theme | ubuntu-mobile-icons, |
1619 | ${misc:Depends}, |
1620 | Description: Music player for Ubuntu Touch |
1621 | @@ -32,9 +35,7 @@ |
1622 | |
1623 | Package: music-app-autopilot |
1624 | Architecture: all |
1625 | -Depends: gstreamer0.10-fluendo-mp3, |
1626 | - gstreamer1.0-fluendo-mp3, |
1627 | - libautopilot-qt (>= 1.4), |
1628 | +Depends: libautopilot-qt (>= 1.4), |
1629 | libqt5test5, |
1630 | music-app (= ${source:Version}), |
1631 | python-mock, |
1632 | |
1633 | === modified file 'meta-database.js' |
1634 | --- meta-database.js 2014-05-02 04:03:50 +0000 |
1635 | +++ meta-database.js 2014-06-19 01:49:30 +0000 |
1636 | @@ -1,6 +1,8 @@ |
1637 | /* |
1638 | - * Copyright (C) 2013 Victor Thompson <victor.thompson@gmail.com> |
1639 | - * Daniel Holm <d.holmen@gmail.com> |
1640 | + * Copyright (C) 2013, 2014 |
1641 | + * Andrew Hayzen <ahayzen@gmail.com> |
1642 | + * Daniel Holm <d.holmen@gmail.com> |
1643 | + * Victor Thompson <victor.thompson@gmail.com> |
1644 | * |
1645 | * This program is free software; you can redistribute it and/or modify |
1646 | * it under the terms of the GNU General Public License as published by |
1647 | @@ -15,9 +17,6 @@ |
1648 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1649 | */ |
1650 | |
1651 | -var buffer = []; // Buffer of metadata to write to the db |
1652 | -var maxBufferLength = 8000; // Maximum size of buffer before auto write to db |
1653 | - |
1654 | // First, let's create a short helper function to get the database connection |
1655 | function getDatabase() { |
1656 | return LocalStorage.openDatabaseSync("music-app-metadata", "1.0", "StorageDatabase", 1000000); |
1657 | @@ -30,19 +29,8 @@ |
1658 | function(tx) { |
1659 | // Create the table if it doesn't already exist |
1660 | // If the table exists, this is skipped |
1661 | - //tx.executeSql('DROP TABLE metadata'); |
1662 | - tx.executeSql('CREATE TABLE IF NOT EXISTS metadata(file TEXT UNIQUE, title TEXT, artist TEXT, album TEXT, cover TEXT, year TEXT, number TEXT, length TEXT, genre TEXT)'); |
1663 | - createRecent(); |
1664 | - }); |
1665 | -} |
1666 | -function reset() { |
1667 | - var db = getDatabase(); |
1668 | - db.transaction( |
1669 | - function(tx) { |
1670 | - // Create the table if it doesn't already exist |
1671 | - // If the table exists, this is skipped |
1672 | - tx.executeSql('DROP TABLE IF EXISTS metadata'); |
1673 | - tx.executeSql('CREATE TABLE IF NOT EXISTS metadata(file TEXT UNIQUE, title TEXT, artist TEXT, album TEXT, cover TEXT, year TEXT, number TEXT, length TEXT, genre TEXT)'); |
1674 | + tx.executeSql('DROP TABLE IF EXISTS metadata'); // TODO: drop recent as well to reset data |
1675 | + |
1676 | createRecent(); |
1677 | }); |
1678 | } |
1679 | @@ -67,348 +55,6 @@ |
1680 | }); |
1681 | } |
1682 | |
1683 | -// This function is used to flush the buffer of metadata to the db |
1684 | -function writeDb() |
1685 | -{ |
1686 | - var db = getDatabase(); |
1687 | - var res = ""; |
1688 | - var i; |
1689 | - |
1690 | - console.debug("Writing DB"); |
1691 | - console.debug(buffer.length); |
1692 | - |
1693 | - // Keep within one transaction for performance win |
1694 | - db.transaction(function(tx) { |
1695 | - // Loop through all the metadata in the buffer |
1696 | - for (i=0; i < buffer.length; i++) |
1697 | - { |
1698 | - var res = tx.executeSql('INSERT OR REPLACE INTO metadata VALUES (?,?,?,?,?,?,?,?,?);', buffer[i]); |
1699 | - |
1700 | - if (res.rowsAffected <= 0) |
1701 | - { |
1702 | - // Nothing was added error occured? |
1703 | - console.debug("Error occured writing to db for ", buffer[i]); |
1704 | - } |
1705 | - } |
1706 | - }); |
1707 | - |
1708 | - buffer = []; // Clear buffer |
1709 | -} |
1710 | - |
1711 | -// This function is used to write meta data into the database |
1712 | -function setMetadata(record) { |
1713 | - buffer.push([record.file,record.title,record.artist,record.album,record.cover,record.year,record.number,record.length,record.genre]); // Add metadata to buffer |
1714 | - |
1715 | - if (buffer.length >= maxBufferLength) |
1716 | - { |
1717 | - console.debug("Buffer full, flushing buffer to disk"); |
1718 | - writeDb(); |
1719 | - } |
1720 | -} |
1721 | - |
1722 | - |
1723 | -function removeFiles(files) |
1724 | -{ |
1725 | - var db = getDatabase(); |
1726 | - |
1727 | - db.transaction(function(tx) { |
1728 | - for (var i=0; i < files.length; i++) |
1729 | - { |
1730 | - for (var k in files[i]) |
1731 | - { |
1732 | - tx.executeSql('DELETE FROM metadata WHERE file=?;', files[i]["file"]); |
1733 | - } |
1734 | - } |
1735 | - }); |
1736 | -} |
1737 | - |
1738 | -// This function is used to retrieve meta data from the database |
1739 | -function getMetadata(file) { |
1740 | - var db = getDatabase(); |
1741 | - var res=""; |
1742 | - |
1743 | - try { |
1744 | - db.transaction(function(tx) { |
1745 | - var rs = tx.executeSql('SELECT * FROM metadata WHERE file=?;', [file]); // tries to get the title of track |
1746 | - |
1747 | - if (rs.rows.length > 0) { |
1748 | - res = rs.rows.item(0); |
1749 | - } else { |
1750 | - res = "Unknown"; |
1751 | - } |
1752 | - }) |
1753 | - } catch(e) { |
1754 | - return ""; |
1755 | - } |
1756 | - |
1757 | - // The function returns “Unknown” if the setting was not found in the database |
1758 | - // For more advanced projects, this should probably be handled through error codes |
1759 | - return res |
1760 | -} |
1761 | - |
1762 | -// This function is used to retrieve meta data from the database |
1763 | -function hasCover(file) { |
1764 | - var db = getDatabase(); |
1765 | - var res = false; |
1766 | - |
1767 | - try { |
1768 | - db.transaction(function(tx) { |
1769 | - var rs = tx.executeSql('SELECT cover FROM metadata WHERE file = ?;', [file]); // tries to get the cover art of track |
1770 | - |
1771 | - if (rs.rows.length > 0) { |
1772 | - res = rs.rows.item(0).cover !== "" |
1773 | - } |
1774 | - }) |
1775 | - } catch(e) { |
1776 | - return false; |
1777 | - } |
1778 | - |
1779 | - // The function returns false if cover art was not found in the database |
1780 | - return res |
1781 | -} |
1782 | - |
1783 | - |
1784 | -function printValues() { |
1785 | - var db = getDatabase(); |
1786 | - db.transaction( function(tx) { |
1787 | - var rs = tx.executeSql("SELECT * FROM metadata"); |
1788 | - for(var i = 0; i < rs.rows.length; i++) { |
1789 | - var dbItem = rs.rows.item(i); |
1790 | - console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover); |
1791 | - } |
1792 | - }); |
1793 | -} |
1794 | - |
1795 | - |
1796 | -function getAll() { |
1797 | - var res = []; |
1798 | - var db = getDatabase(); |
1799 | - db.transaction( function(tx) { |
1800 | - var rs = tx.executeSql("SELECT * FROM metadata ORDER BY title COLLATE NOCASE ASC, artist COLLATE NOCASE ASC, album COLLATE NOCASE ASC, CAST(number AS int) ASC"); |
1801 | - for(var i = 0; i < rs.rows.length; i++) { |
1802 | - var dbItem = rs.rows.item(i); |
1803 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1804 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1805 | - } |
1806 | - }); |
1807 | - return res; |
1808 | -} |
1809 | - |
1810 | -function getAllFileOrder() { |
1811 | - var res = []; |
1812 | - var db = getDatabase(); |
1813 | - db.transaction( function(tx) { |
1814 | - var rs = tx.executeSql("SELECT * FROM metadata ORDER BY file COLLATE NOCASE ASC"); |
1815 | - for(var i = 0; i < rs.rows.length; i++) { |
1816 | - var dbItem = rs.rows.item(i); |
1817 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1818 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, number:dbItem.number, year:dbItem.year, genre:dbItem.genre}); |
1819 | - } |
1820 | - }); |
1821 | - return res; |
1822 | -} |
1823 | - |
1824 | -function getArtists() { |
1825 | - var res = []; |
1826 | - var db = getDatabase(); |
1827 | - db.transaction( function(tx) { |
1828 | - var rs = tx.executeSql("SELECT * FROM metadata GROUP BY artist ORDER BY artist COLLATE NOCASE ASC"); |
1829 | - for(var i = 0; i < rs.rows.length; i++) { |
1830 | - var dbItem = rs.rows.item(i); |
1831 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1832 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1833 | - } |
1834 | - }); |
1835 | - return res; |
1836 | -} |
1837 | - |
1838 | -function getArtistTracks(artist) { |
1839 | - var res = []; |
1840 | - var db = getDatabase(); |
1841 | - db.transaction( function(tx) { |
1842 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE artist=? ORDER BY artist COLLATE NOCASE ASC, year ASC, CAST(number AS int) ASC", [artist]); |
1843 | - for(var i = 0; i < rs.rows.length; i++) { |
1844 | - var dbItem = rs.rows.item(i); |
1845 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1846 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1847 | - } |
1848 | - }); |
1849 | - return res; |
1850 | -} |
1851 | - |
1852 | -function getArtistAlbums(artist) { |
1853 | - var res = []; |
1854 | - var db = getDatabase(); |
1855 | - db.transaction( function(tx) { |
1856 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE artist=? GROUP BY album ORDER BY year ASC, CAST(number AS int) ASC", [artist]); |
1857 | - for(var i = 0; i < rs.rows.length; i++) { |
1858 | - var dbItem = rs.rows.item(i); |
1859 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1860 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1861 | - } |
1862 | - }); |
1863 | - return res; |
1864 | -} |
1865 | - |
1866 | -function getArtistCovers(artist) { |
1867 | - var res = []; |
1868 | - var db = getDatabase(); |
1869 | - try { |
1870 | - db.transaction( function(tx) { |
1871 | - var rs = tx.executeSql("SELECT cover FROM metadata WHERE artist=? AND cover <> '' ORDER BY album COLLATE NOCASE ASC", [artist]); |
1872 | - for(var i = 0; i < rs.rows.length; i++) { |
1873 | - var dbItem = rs.rows.item(i); |
1874 | - //console.log("Cover:"+ dbItem.cover+" Size:"+res.length); |
1875 | - if (res.indexOf(dbItem.cover) == -1) res.push(dbItem.cover); |
1876 | - } |
1877 | - }); |
1878 | - } catch(e) { |
1879 | - return []; |
1880 | - } |
1881 | - |
1882 | - return res; |
1883 | -} |
1884 | - |
1885 | -function getAlbumCover(album) { |
1886 | - var res = ""; |
1887 | - var db = getDatabase(); |
1888 | - try { |
1889 | - db.transaction( function(tx) { |
1890 | - var rs = tx.executeSql("SELECT cover FROM metadata WHERE album=? ORDER BY cover DESC", [album]); |
1891 | - var dbItem = rs.rows.item(0); |
1892 | - //console.log("Cover:"+ dbItem.cover+" Size:"+res.length); |
1893 | - if (rs.rows.length > 0) res = rs.rows.item(0).cover; |
1894 | - }); |
1895 | - } catch(e) { |
1896 | - return ""; |
1897 | - } |
1898 | - |
1899 | - return res; |
1900 | -} |
1901 | - |
1902 | -function getArtistAlbumCount(artist) { |
1903 | - var res = 0; |
1904 | - var db = getDatabase(); |
1905 | - db.transaction( function(tx) { |
1906 | - var rs = tx.executeSql("SELECT count(DISTINCT album) AS value FROM metadata WHERE artist=?", [artist]); |
1907 | - if (rs.rows.item(0).value > 0) { |
1908 | - res = rs.rows.item(0).value; |
1909 | - } else { |
1910 | - res = 0; |
1911 | - } |
1912 | - }); |
1913 | - return res; |
1914 | -} |
1915 | - |
1916 | -function getAlbums() { |
1917 | - var res = []; |
1918 | - var db = getDatabase(); |
1919 | - try { |
1920 | - db.transaction( function(tx) { |
1921 | - var rs = tx.executeSql("SELECT * FROM metadata GROUP BY album ORDER BY album COLLATE NOCASE ASC"); |
1922 | - for(var i = 0; i < rs.rows.length; i++) { |
1923 | - var dbItem = rs.rows.item(i); |
1924 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1925 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1926 | - } |
1927 | - }); |
1928 | - } catch(e) { |
1929 | - return []; |
1930 | - } |
1931 | - |
1932 | - return res; |
1933 | -} |
1934 | - |
1935 | -function getAlbumTracks(album) { |
1936 | - var res = []; |
1937 | - var db = getDatabase(); |
1938 | - //console.log("Album: " + album); |
1939 | - db.transaction( function(tx) { |
1940 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE album=? ORDER BY artist COLLATE NOCASE ASC, album COLLATE NOCASE ASC, CAST(number AS int) ASC", [album]); |
1941 | - for(var i = 0; i < rs.rows.length; i++) { |
1942 | - var dbItem = rs.rows.item(i); |
1943 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1944 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1945 | - } |
1946 | - }); |
1947 | - return res; |
1948 | -} |
1949 | - |
1950 | -function getArtistAlbumTracks(artist, album) { |
1951 | - var res = []; |
1952 | - var db = getDatabase(); |
1953 | - //console.log("Album: " + album); |
1954 | - db.transaction( function(tx) { |
1955 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE artist=? AND album=? ORDER BY artist COLLATE NOCASE ASC, album COLLATE NOCASE ASC, CAST(number AS int) ASC", [artist, album]); |
1956 | - for(var i = 0; i < rs.rows.length; i++) { |
1957 | - var dbItem = rs.rows.item(i); |
1958 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1959 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1960 | - } |
1961 | - }); |
1962 | - return res; |
1963 | -} |
1964 | - |
1965 | -function getGenres() { |
1966 | - var res = []; |
1967 | - var db = getDatabase(); |
1968 | - db.transaction( function(tx) { |
1969 | - var rs = tx.executeSql("SELECT *, count(genre) AS total FROM metadata GROUP BY genre ORDER BY genre COLLATE NOCASE ASC"); |
1970 | - for(var i = 0; i < rs.rows.length; i++) { |
1971 | - var dbItem = rs.rows.item(i); |
1972 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1973 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre, total: dbItem.total}); |
1974 | - } |
1975 | - }); |
1976 | - return res; |
1977 | -} |
1978 | - |
1979 | -function getGenreTracks(genre) { |
1980 | - var res = []; |
1981 | - var db = getDatabase(); |
1982 | - //console.log("Genre: " + genre); |
1983 | - db.transaction( function(tx) { |
1984 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE genre=? ORDER BY artist COLLATE NOCASE ASC, album COLLATE NOCASE ASC, CAST(number AS int) ASC", [genre]); |
1985 | - for(var i = 0; i < rs.rows.length; i++) { |
1986 | - var dbItem = rs.rows.item(i); |
1987 | - //console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
1988 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
1989 | - } |
1990 | - }); |
1991 | - return res; |
1992 | -} |
1993 | - |
1994 | -function getGenreCovers(genre) { |
1995 | - var res = []; |
1996 | - var db = getDatabase(); |
1997 | - try { |
1998 | - db.transaction( function(tx) { |
1999 | - var rs = tx.executeSql("SELECT cover FROM metadata WHERE genre=? AND cover <> '' ORDER BY artist COLLATE NOCASE ASC", [genre]); |
2000 | - for(var i = 0; i < rs.rows.length; i++) { |
2001 | - if (res.indexOf(rs.rows.item(i).cover) === -1) { |
2002 | - res.push(rs.rows.item(i).cover); |
2003 | - } |
2004 | - } |
2005 | - }); |
2006 | - } catch(e) { |
2007 | - return []; |
2008 | - } |
2009 | - |
2010 | - return res; |
2011 | -} |
2012 | - |
2013 | - |
2014 | -function size() { |
2015 | - var db = getDatabase(); |
2016 | - var res=""; |
2017 | - |
2018 | - db.transaction( function(tx) { |
2019 | - var rs = tx.executeSql("SELECT count(*) FROM metadata"); |
2020 | - res = rs.rows.item(0).value; |
2021 | - }); |
2022 | - return res; |
2023 | -} |
2024 | - |
2025 | // This function is used to insert a recent item into the database |
2026 | function addRecent(title, title2, cover, key, type) { |
2027 | var db = getDatabase(); |
2028 | @@ -436,21 +82,20 @@ |
2029 | var rs = tx.executeSql("SELECT * FROM recent ORDER BY time DESC LIMIT 15"); |
2030 | for(var i = 0; i < rs.rows.length; i++) { |
2031 | var dbItem = rs.rows.item(i); |
2032 | - console.log("Time:"+ dbItem.time + ", Key:"+dbItem.key + ", Title:"+dbItem.title + ", Title2:"+dbItem.title2 + ", Cover:"+dbItem.cover + ", Type:"+dbItem.type); |
2033 | + console.log("Time:"+ dbItem.time + ", Key:"+dbItem.key + ", Title:"+dbItem.title + ", Title2:"+dbItem.title2 + ", Type:"+dbItem.type); |
2034 | |
2035 | if (dbItem.type === "album") |
2036 | { |
2037 | res.push({time:dbItem.time, |
2038 | title:dbItem.title || i18n.tr("Unknown Album"), |
2039 | title2:dbItem.title2 || i18n.tr("Unknown Artist"), |
2040 | - cover:dbItem.cover, |
2041 | key:dbItem.key || i18n.tr("Unknown Album"), |
2042 | type:dbItem.type |
2043 | }); |
2044 | } |
2045 | else |
2046 | { |
2047 | - res.push({time:dbItem.time, title:dbItem.title, title2:dbItem.title2, cover:dbItem.cover, key:dbItem.key, type:dbItem.type}); |
2048 | + res.push({time:dbItem.time, title:dbItem.title, title2:dbItem.title2, key:dbItem.key, type:dbItem.type}); |
2049 | } |
2050 | } |
2051 | }); |
2052 | @@ -474,20 +119,3 @@ |
2053 | ); |
2054 | return res === 0; |
2055 | } |
2056 | - |
2057 | -// Search track LIKE |
2058 | -function search(input) { |
2059 | - console.debug("Got a new search: "+input) |
2060 | - input = "%" + input + "%" // workaround |
2061 | - var res = []; |
2062 | - var db = getDatabase(); |
2063 | - db.transaction( function(tx) { |
2064 | - var rs = tx.executeSql("SELECT * FROM metadata WHERE title LIKE ? OR artist LIKE ? OR album LIKE ? OR genre LIKE ?;", [input,input,input,input]); // WRONG! WHy? |
2065 | - for(var i = 0; i < rs.rows.length; i++) { |
2066 | - var dbItem = rs.rows.item(i); |
2067 | - console.log("Artist:"+ dbItem.artist + ", Album:"+dbItem.album + ", Title:"+dbItem.title + ", File:"+dbItem.file + ", Art:"+dbItem.cover + ", Genre:"+dbItem.genre); |
2068 | - res.push({artist:dbItem.artist, album:dbItem.album, title:dbItem.title, file:dbItem.file, cover:dbItem.cover, length:dbItem.length, year:dbItem.year, genre:dbItem.genre}); |
2069 | - } |
2070 | - }); |
2071 | - return res; |
2072 | -} |
2073 | |
2074 | === modified file 'music-app.qml' |
2075 | --- music-app.qml 2014-05-08 22:58:35 +0000 |
2076 | +++ music-app.qml 2014-06-19 01:49:30 +0000 |
2077 | @@ -1,7 +1,8 @@ |
2078 | /* |
2079 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
2080 | - * Daniel Holm <d.holmen@gmail.com> |
2081 | - * Victor Thompson <victor.thompson@gmail.com> |
2082 | + * Copyright (C) 2013, 2014 |
2083 | + * Andrew Hayzen <ahayzen@gmail.com> |
2084 | + * Daniel Holm <d.holmen@gmail.com> |
2085 | + * Victor Thompson <victor.thompson@gmail.com> |
2086 | * |
2087 | * This program is free software; you can redistribute it and/or modify |
2088 | * it under the terms of the GNU General Public License as published by |
2089 | @@ -21,8 +22,8 @@ |
2090 | import Ubuntu.Components.ListItems 0.1 |
2091 | import Ubuntu.Components.Popups 0.1 |
2092 | import Ubuntu.Components.ListItems 0.1 as ListItem |
2093 | +import Ubuntu.MediaScanner 0.1 |
2094 | import Ubuntu.Unity.Action 1.0 as UnityActions |
2095 | -import org.nemomobile.grilo 0.1 |
2096 | import QtMultimedia 5.0 |
2097 | import QtQuick.LocalStorage 2.0 |
2098 | import QtQuick.XmlListModel 2.0 |
2099 | @@ -199,9 +200,6 @@ |
2100 | actions: [searchAction, nextAction, playsAction, prevAction, stopAction, backAction] |
2101 | |
2102 | // signal to open new URIs |
2103 | - // TODO currently this only allows playing file:// URIs of known files |
2104 | - // (already in the database), not e.g. http:// URIs or files in directories |
2105 | - // not picked up by Grilo |
2106 | Connections { |
2107 | id: uriHandler |
2108 | target: UriHandler |
2109 | @@ -214,33 +212,29 @@ |
2110 | return; |
2111 | } |
2112 | |
2113 | - // Get tracks |
2114 | - var tracks = Library.getArtistAlbumTracks(decodeURIComponent(split[0]), decodeURIComponent(split[1])); |
2115 | + // Filter by artist and album |
2116 | + songsAlbumArtistModel.artist = decodeURIComponent(split[0]); |
2117 | + songsAlbumArtistModel.album = decodeURIComponent(split[1]); |
2118 | |
2119 | - if (tracks.length === 0) { |
2120 | + // Play album it tracks exist |
2121 | + if (songsAlbumArtistModel.rowCount > 0) { |
2122 | + trackClicked(songsAlbumArtistModel, 0, true); |
2123 | + } |
2124 | + else { |
2125 | console.debug("Unknown artist-album " + uri + ", skipping") |
2126 | return; |
2127 | } |
2128 | - |
2129 | - // Enqueue |
2130 | - for (var track in tracks) { |
2131 | - trackQueue.append(tracks[track]); |
2132 | - } |
2133 | - |
2134 | - // Play first track |
2135 | - trackClicked(trackQueue, 0, true); |
2136 | } |
2137 | |
2138 | function processFile(uri, play) { |
2139 | uri = decodeURIComponent(uri); |
2140 | |
2141 | - // search for path in library |
2142 | - var library = Library.getAll(); |
2143 | var track = false; |
2144 | |
2145 | - for (var item in library) { |
2146 | - if (decodeURIComponent(library[item].file) === uri) { |
2147 | - track = library[item]; |
2148 | + // Search for track in songs model |
2149 | + for (var i=0; i < allSongsModel.rowCount; i++) { |
2150 | + if (decodeURIComponent(allSongsModel.get(i, allSongsModel.RoleModelData).filename) === uri) { |
2151 | + track = allSongsModel.get(i, allSongsModel.RoleModelData); |
2152 | break; |
2153 | } |
2154 | } |
2155 | @@ -255,7 +249,7 @@ |
2156 | |
2157 | // play first URI |
2158 | if (play) { |
2159 | - trackClicked(trackQueue, 0, true) |
2160 | + trackQueueClick(0); |
2161 | } |
2162 | } |
2163 | |
2164 | @@ -340,8 +334,7 @@ |
2165 | Settings.setSetting("repeat", "0") // default state of repeat |
2166 | //Settings.setSetting("scrobble", "0") // default state of scrobble |
2167 | } |
2168 | - Library.reset() |
2169 | - //Library.initialize(); |
2170 | + Library.initialize(); |
2171 | |
2172 | // initialize playlists |
2173 | Playlists.initializePlaylists() |
2174 | @@ -355,13 +348,27 @@ |
2175 | // push the page to view |
2176 | pageStack.push(tabs) |
2177 | |
2178 | + loadedUI = true; |
2179 | + |
2180 | // TODO: Switch tabs back and forth to get the background color in the |
2181 | // header to work properly. |
2182 | tabs.selectedTabIndex = 1 |
2183 | tabs.selectedTabIndex = 0 |
2184 | + |
2185 | + // Run post load |
2186 | + tabs.ensurePopulated(tabs.selectedTab); |
2187 | + |
2188 | + if (args.values.url) { |
2189 | + uriHandler.process(args.values.url, true); |
2190 | + } |
2191 | + |
2192 | + // Show toolbar and start timer if there is music |
2193 | + if (!emptyPage.noMusic) { |
2194 | + musicToolbar.showToolbar(); |
2195 | + musicToolbar.startAutohideTimer(); |
2196 | + } |
2197 | } |
2198 | |
2199 | - |
2200 | // VARIABLES |
2201 | property string musicName: i18n.tr("Music") |
2202 | property string appVersion: '1.2' |
2203 | @@ -371,16 +378,13 @@ |
2204 | property string lastfmpassword |
2205 | property string timestamp // used to scrobble |
2206 | property var chosenElement: null |
2207 | - property LibraryListModel currentModel: null // Current model being used |
2208 | - property var currentQuery: null |
2209 | - property var currentParam: null |
2210 | - property bool queueChanged: false |
2211 | property bool toolbarShown: musicToolbar.shown |
2212 | signal collapseExpand(); |
2213 | signal collapseSwipeDelete(int index); |
2214 | signal onToolbarShownChanged(bool shown, var currentPage, var currentTab) |
2215 | |
2216 | property bool wideAspect: width >= units.gu(70) |
2217 | + property bool loadedUI: false // property to detect if the UI has finished |
2218 | |
2219 | // FUNCTIONS |
2220 | |
2221 | @@ -393,28 +397,20 @@ |
2222 | } |
2223 | } |
2224 | |
2225 | - // Add items from a stored query in libraryModel into the queue |
2226 | - function addQueueFromModel(libraryModel) |
2227 | + function addQueueFromModel(model) |
2228 | { |
2229 | - var items; |
2230 | - |
2231 | - if (libraryModel.query === null) |
2232 | - { |
2233 | - return |
2234 | - } |
2235 | - |
2236 | - if (libraryModel.param === null) |
2237 | - { |
2238 | - items = libraryModel.query() |
2239 | - } |
2240 | - else |
2241 | - { |
2242 | - items = libraryModel.query(libraryModel.param) |
2243 | - } |
2244 | - |
2245 | - for (var key in items) |
2246 | - { |
2247 | - trackQueue.append(items[key]) |
2248 | + // TODO: remove once playlists uses U1DB |
2249 | + if (model.hasOwnProperty("linkLibraryListModel")) { |
2250 | + model = model.linkLibraryListModel; |
2251 | + } |
2252 | + |
2253 | + for (var i=0; i < model.rowCount; i++) { |
2254 | + var item = model.get(i, model.RoleModelData); |
2255 | + if (item.art !== undefined && (item.art === "" || item.art === null)) { |
2256 | + item.art = "image://albumart/artist=" + item.author + "&album=" + item.album |
2257 | + } |
2258 | + |
2259 | + trackQueue.model.append(makeDict(item)); |
2260 | } |
2261 | } |
2262 | |
2263 | @@ -430,64 +426,39 @@ |
2264 | return minutes + ":" + (seconds<10 ? "0"+seconds : seconds); |
2265 | } |
2266 | |
2267 | - function trackClicked(libraryModel, index, play) |
2268 | - { |
2269 | + // Make dictionary from model item |
2270 | + function makeDict(model) { |
2271 | + return { |
2272 | + album: model.album, |
2273 | + author: model.author, |
2274 | + filename: model.filename, |
2275 | + title: model.title |
2276 | + }; |
2277 | + } |
2278 | + |
2279 | + function trackClicked(model, index, play) { |
2280 | + // TODO: remove once playlists uses U1DB |
2281 | + if (model.hasOwnProperty("linkLibraryListModel")) { |
2282 | + model = model.linkLibraryListModel; |
2283 | + } |
2284 | + |
2285 | + var file = Qt.resolvedUrl(model.get(index, model.RoleModelData).filename); |
2286 | + |
2287 | play = play === undefined ? true : play // default play to true |
2288 | |
2289 | - if (index > libraryModel.model.count - 1 || index < 0) { |
2290 | - customdebug("Incorrect index given to trackClicked.") |
2291 | + // If same track and on now playing page then toggle |
2292 | + if (musicToolbar.currentPage === nowPlaying && |
2293 | + Qt.resolvedUrl(trackQueue.model.get(player.currentIndex).filename) === file) { |
2294 | + player.toggle() |
2295 | return; |
2296 | } |
2297 | |
2298 | - var file = Qt.resolvedUrl(libraryModel.model.get(index).file) |
2299 | - |
2300 | - // Clear the play queue and load the new tracks - if not trackQueue |
2301 | - // Don't reload queue if model, query and parameters are the same |
2302 | - // Same file different pages is treated as a new session |
2303 | - if (libraryModel !== trackQueue && |
2304 | - (currentModel !== libraryModel || |
2305 | - currentQuery !== libraryModel.query || |
2306 | - currentParam !== libraryModel.param || |
2307 | - queueChanged === true)) |
2308 | - { |
2309 | - trackQueue.model.clear() |
2310 | - addQueueFromModel(libraryModel) |
2311 | - } |
2312 | - else if (player.source == file && |
2313 | - player.currentIndex === index) |
2314 | - { |
2315 | - // Same track so just toggle playing state |
2316 | - if (play === true) { |
2317 | - console.log("Is current track: "+player.playbackState) |
2318 | - |
2319 | - // Show the Now Playing page and make sure the track is visible |
2320 | - tabs.pushNowPlaying(); |
2321 | - nowPlaying.ensureVisibleIndex = index; |
2322 | - |
2323 | - musicToolbar.showToolbar(); |
2324 | - |
2325 | - if (musicToolbar.currentPage == nowPlaying) { |
2326 | - player.toggle() |
2327 | - } |
2328 | - } |
2329 | - |
2330 | - return |
2331 | - } |
2332 | - |
2333 | - // Current index must be updated before player.source |
2334 | - currentModel = libraryModel |
2335 | - currentQuery = libraryModel.query |
2336 | - currentParam = libraryModel.param |
2337 | - |
2338 | - if (Qt.resolvedUrl(trackQueue.model.get(index).file) != file) { |
2339 | - index = trackQueue.indexOf(file) // pick given index first |
2340 | - } |
2341 | - queueChanged = false |
2342 | - |
2343 | - console.log("Click of fileName: " + file) |
2344 | - |
2345 | - if (play === true) { |
2346 | - player.playSong(file, index) |
2347 | + trackQueue.model.clear(); // clear the old model |
2348 | + |
2349 | + addQueueFromModel(model); |
2350 | + |
2351 | + if (play) { |
2352 | + player.playSong(file, index); |
2353 | |
2354 | // Show the Now Playing page and make sure the track is visible |
2355 | tabs.pushNowPlaying(); |
2356 | @@ -496,34 +467,59 @@ |
2357 | musicToolbar.showToolbar(); |
2358 | } |
2359 | else { |
2360 | - player.source = file |
2361 | + player.source = file; |
2362 | } |
2363 | |
2364 | collapseExpand(); // collapse all expands if track clicked |
2365 | - |
2366 | - return file |
2367 | + } |
2368 | + |
2369 | + function trackQueueClick(index) { |
2370 | + if (player.currentIndex === index) { |
2371 | + player.toggle(); |
2372 | + } |
2373 | + else { |
2374 | + player.playSong(trackQueue.model.get(index).filename, index); |
2375 | + } |
2376 | + |
2377 | + // Show the Now Playing page and make sure the track is visible |
2378 | + tabs.pushNowPlaying(); |
2379 | + nowPlaying.ensureVisibleIndex = index; |
2380 | + |
2381 | + musicToolbar.showToolbar(); |
2382 | } |
2383 | |
2384 | function playRandomSong(shuffle) |
2385 | { |
2386 | trackQueue.model.clear(); |
2387 | |
2388 | - var items = Library.getAll(); |
2389 | - |
2390 | - for (var key in items) { |
2391 | - trackQueue.append(items[key]); |
2392 | - } |
2393 | - |
2394 | var now = new Date(); |
2395 | var seed = now.getSeconds(); |
2396 | - var index = Math.floor(trackQueue.model.count * Math.random(seed)); |
2397 | - |
2398 | - console.debug("THIS", index); |
2399 | + var index = Math.floor(allSongsModel.rowCount * Math.random(seed)); |
2400 | |
2401 | player.shuffle = shuffle === undefined ? true : shuffle; |
2402 | - trackClicked(trackQueue, |
2403 | - index, |
2404 | - true); |
2405 | + |
2406 | + trackClicked(allSongsModel, index, true) |
2407 | + } |
2408 | + |
2409 | + // Load mediascanner store |
2410 | + MediaStore { |
2411 | + id: musicStore |
2412 | + } |
2413 | + |
2414 | + SongsModel { |
2415 | + id: allSongsModel |
2416 | + // HACK: Temporarily setting limit to 500 to ensure model |
2417 | + // is populated. See lp:1326753 |
2418 | + limit: 500 |
2419 | + store: musicStore |
2420 | + } |
2421 | + |
2422 | + SongsModel { |
2423 | + id: songsAlbumArtistModel |
2424 | + // HACK: Temporarily setting limit to 500 to ensure model |
2425 | + // is populated. See lp:1326753 |
2426 | + limit: 500 |
2427 | + store: musicStore |
2428 | } |
2429 | |
2430 | // WHERE THE MAGIC HAPPENS |
2431 | @@ -583,211 +579,19 @@ |
2432 | } |
2433 | } |
2434 | |
2435 | - GriloModel { |
2436 | - id: griloModel |
2437 | - property bool loaded: false |
2438 | - |
2439 | - source: GriloBrowse { |
2440 | - id: browser |
2441 | - source: "grl-mediascanner" |
2442 | - registry: registry |
2443 | - metadataKeys: [GriloBrowse.Title] |
2444 | - typeFilter: [GriloBrowse.Audio] |
2445 | - Component.onCompleted: { |
2446 | - console.log(browser.supportedKeys); |
2447 | - console.log(browser.slowKeys); |
2448 | - refresh(); |
2449 | - console.log("Refreshing"); |
2450 | - } |
2451 | - |
2452 | - onAvailableChanged: { |
2453 | - console.log("Available ? " + available); |
2454 | - if (available === true) { |
2455 | - console.log("griloModel.count " + griloModel.count) |
2456 | - } |
2457 | - } |
2458 | - onBaseMediaChanged: refresh(); |
2459 | - |
2460 | - /* Check if the file (needle) exists in the library (haystack) |
2461 | - * Searches the the haystack using a binary search |
2462 | - * |
2463 | - * false if the file in in grilo but not in the haystack |
2464 | - * positive if the file is the same (number is the actual index) |
2465 | - * negative if the file has changed, actual index is -(i + 1) |
2466 | - */ |
2467 | - function exists(haystack, needle) |
2468 | - { |
2469 | - var keyToFind = needle["file"]; |
2470 | - |
2471 | - var upper = haystack.length - 1; |
2472 | - var lower = 0; |
2473 | - var i = Math.floor(haystack.length / 2); |
2474 | - |
2475 | - while (upper >= lower) |
2476 | - { |
2477 | - var key = haystack[i]["file"]; |
2478 | - |
2479 | - if (keyToFind < key) |
2480 | - { |
2481 | - upper = i - 1; |
2482 | - } |
2483 | - else if (keyToFind > key) |
2484 | - { |
2485 | - lower = i + 1; |
2486 | - } |
2487 | - else |
2488 | - { |
2489 | - var found = false; |
2490 | - |
2491 | - for (var k in haystack[i]) |
2492 | - { |
2493 | - if (haystack[i][k] === needle[k]) |
2494 | - { |
2495 | - found = true; |
2496 | - } |
2497 | - else |
2498 | - { |
2499 | - found = false; |
2500 | - break; |
2501 | - } |
2502 | - } |
2503 | - |
2504 | - if (found === true) |
2505 | - { |
2506 | - return i; // in grilo and lib - same |
2507 | - } |
2508 | - else |
2509 | - { |
2510 | - return -i - 1; // in grilo and lib - different |
2511 | - } |
2512 | - } |
2513 | - |
2514 | - i = Math.floor((upper + lower) / 2); |
2515 | - } |
2516 | - |
2517 | - return false; // in grilo not in lib |
2518 | - } |
2519 | - |
2520 | - onFinished: { |
2521 | - // FIXME: remove when grilo is fixed |
2522 | - var files = []; |
2523 | - var duplicates = 0; |
2524 | - |
2525 | - for (var i = 0; i < griloModel.count; i++) |
2526 | - { |
2527 | - var media = griloModel.get(i) |
2528 | - var file = media.url.toString() |
2529 | - if (file.indexOf("file://") === 0) |
2530 | - { |
2531 | - file = file.slice(7, file.length) |
2532 | - } |
2533 | - |
2534 | - // FIXME: grilo can supply duplicates |
2535 | - if (files.indexOf(file) > -1) |
2536 | - { |
2537 | - duplicates++; |
2538 | - continue; |
2539 | - } |
2540 | - files.push(file); |
2541 | - |
2542 | - var record = { |
2543 | - artist: media.artist || i18n.tr("Unknown Artist"), |
2544 | - album: media.album || i18n.tr("Unknown Album"), |
2545 | - title: media.title || file, |
2546 | - file: file, |
2547 | - cover: media.thumbnail.toString() || "", |
2548 | - length: media.duration.toString(), |
2549 | - number: media.trackNumber, |
2550 | - year: media.year.toString() !== "0" ? media.year.toString(): i18n.tr("Unknown Year"), |
2551 | - genre: media.genre || i18n.tr("Unknown Genre") |
2552 | - }; |
2553 | - |
2554 | - //console.log("Artist:"+ media.artist + ", Album:"+media.album + ", Title:"+media.title + ", File:"+file + ", Cover:"+media.thumbnail + ", Number:"+media.trackNumber + ", Genre:"+media.genre); |
2555 | - Library.setMetadata(record) |
2556 | - } |
2557 | - |
2558 | - Library.writeDb() |
2559 | - |
2560 | - console.debug("Grilo duplicates:", duplicates); // FIXME: remove when grilo is fixed |
2561 | - griloModel.loaded = true |
2562 | - |
2563 | - // Show toolbar and start timer if there is music |
2564 | - if (!emptyPage.noMusic || wideAspect) { |
2565 | - musicToolbar.showToolbar(); |
2566 | - musicToolbar.startAutohideTimer(); |
2567 | - } |
2568 | - |
2569 | - tabs.ensurePopulated(tabs.selectedTab); |
2570 | - |
2571 | - if (args.values.url) { |
2572 | - uriHandler.process(args.values.url, true); |
2573 | - } |
2574 | - } |
2575 | - } |
2576 | - } |
2577 | - |
2578 | - GriloRegistry { |
2579 | - id: registry |
2580 | - |
2581 | - Component.onCompleted: { |
2582 | - console.log("Registry is ready"); |
2583 | - loadAll(); |
2584 | - } |
2585 | - } |
2586 | - |
2587 | - LibraryListModel { |
2588 | - id: libraryModel |
2589 | - onPreLoadCompleteChanged: { |
2590 | - if (preLoadComplete) |
2591 | - { |
2592 | - loading.visible = false |
2593 | - tracksTab.loading = false |
2594 | - tracksTab.populated = true |
2595 | - } |
2596 | - } |
2597 | - } |
2598 | - |
2599 | - LibraryListModel { |
2600 | - id: artistModel |
2601 | - onPreLoadCompleteChanged: { |
2602 | - if (preLoadComplete) |
2603 | - { |
2604 | - loading.visible = false |
2605 | - artistsTab.loading = false |
2606 | - artistsTab.populated = true |
2607 | - } |
2608 | - } |
2609 | - } |
2610 | - LibraryListModel { |
2611 | - id: artistTracksModel |
2612 | - } |
2613 | - LibraryListModel { |
2614 | - id: artistAlbumsModel |
2615 | - } |
2616 | - |
2617 | - LibraryListModel { |
2618 | - id: albumModel |
2619 | - onPreLoadCompleteChanged: { |
2620 | - if (preLoadComplete) |
2621 | - { |
2622 | - loading.visible = false |
2623 | - albumsTab.loading = false |
2624 | - albumsTab.populated = true |
2625 | - } |
2626 | - } |
2627 | - } |
2628 | + // TODO: Used by playlisttracks move to U1DB |
2629 | LibraryListModel { |
2630 | id: albumTracksModel |
2631 | } |
2632 | |
2633 | + // TODO: used by recent items move to U1DB |
2634 | LibraryListModel { |
2635 | id: recentModel |
2636 | property bool complete: false |
2637 | onPreLoadCompleteChanged: { |
2638 | complete = true; |
2639 | |
2640 | - if (preLoadComplete && (genreModel.complete || |
2641 | - genreModel.query().length === 0)) |
2642 | + if (preLoadComplete) |
2643 | { |
2644 | loading.visible = false |
2645 | startTab.loading = false |
2646 | @@ -795,63 +599,29 @@ |
2647 | } |
2648 | } |
2649 | } |
2650 | + |
2651 | + // TODO: used by recent albums move to U1DB |
2652 | LibraryListModel { |
2653 | id: recentAlbumTracksModel |
2654 | } |
2655 | + |
2656 | + // TODO: used by recent playlists move to U1DB |
2657 | LibraryListModel { |
2658 | id: recentPlaylistTracksModel |
2659 | } |
2660 | |
2661 | - LibraryListModel { |
2662 | - id: genreModel |
2663 | - property bool complete: false |
2664 | - onPreLoadCompleteChanged: { |
2665 | - complete = true; |
2666 | - |
2667 | - if (preLoadComplete && (recentModel.complete || |
2668 | - recentModel.query().length === 0)) |
2669 | - { |
2670 | - loading.visible = false |
2671 | - startTab.loading = false |
2672 | - startTab.populated = true |
2673 | - } |
2674 | - } |
2675 | - } |
2676 | - |
2677 | - LibraryListModel { |
2678 | - id: genreTracksModel |
2679 | - } |
2680 | - |
2681 | // list of tracks on startup. This is just during development |
2682 | LibraryListModel { |
2683 | id: trackQueue |
2684 | - Connections { |
2685 | - target: trackQueue.model |
2686 | - onCountChanged: queueChanged = true |
2687 | - } |
2688 | |
2689 | function append(listElement) |
2690 | { |
2691 | - model.append({ |
2692 | - "album": listElement.album, |
2693 | - "artist": listElement.artist, |
2694 | - "cover": listElement.cover, |
2695 | - "file": listElement.file, |
2696 | - "title": listElement.title |
2697 | - }) |
2698 | + model.append(makeDict(listElement)) |
2699 | + console.debug(JSON.stringify(makeDict(listElement))); |
2700 | } |
2701 | } |
2702 | |
2703 | - // list of songs, which has been removed. |
2704 | - ListModel { |
2705 | - id: removedTrackQueue |
2706 | - } |
2707 | - |
2708 | - // list of single tracks |
2709 | - ListModel { |
2710 | - id: singleTracksgriloMo |
2711 | - } |
2712 | - |
2713 | + // TODO: list of playlists move to U1DB |
2714 | // create the listmodel to use for playlists |
2715 | LibraryListModel { |
2716 | id: playlistModel |
2717 | @@ -866,11 +636,6 @@ |
2718 | } |
2719 | } |
2720 | |
2721 | - // search model |
2722 | - LibraryListModel { |
2723 | - id: searchModel |
2724 | - } |
2725 | - |
2726 | // load sheets (after model) |
2727 | SongsSheet { |
2728 | id: songsSheet |
2729 | @@ -1002,7 +767,7 @@ |
2730 | title: i18n.tr("Music") |
2731 | visible: false |
2732 | |
2733 | - property bool noMusic: griloModel.count === 0 && griloModel.loaded === true |
2734 | + property bool noMusic: allSongsModel.rowCount === 0 && loadedUI |
2735 | |
2736 | onNoMusicChanged: { |
2737 | if (noMusic) |
2738 | @@ -1027,7 +792,6 @@ |
2739 | Column { |
2740 | anchors.centerIn: parent |
2741 | |
2742 | - |
2743 | Label { |
2744 | anchors.horizontalCenter: parent.horizontalCenter |
2745 | color: styleMusic.libraryEmpty.labelColor |
2746 | @@ -1059,9 +823,9 @@ |
2747 | // First tab is all music |
2748 | Tab { |
2749 | property bool populated: false |
2750 | - property var loader: [recentModel.filterRecent, genreModel.filterGenres, albumModel.filterAlbums] |
2751 | + property var loader: [recentModel.filterRecent] |
2752 | property bool loading: false |
2753 | - property var model: [recentModel, genreModel, albumTracksModel] |
2754 | + property var model: [recentModel, albumTracksModel] |
2755 | id: startTab |
2756 | objectName: "starttab" |
2757 | anchors.fill: parent |
2758 | @@ -1075,10 +839,10 @@ |
2759 | |
2760 | // Second tab is arists |
2761 | Tab { |
2762 | - property bool populated: false |
2763 | - property var loader: [artistModel.filterArtists] |
2764 | + property bool populated: true |
2765 | + property var loader: [] |
2766 | property bool loading: false |
2767 | - property var model: [artistModel, artistAlbumsModel, albumTracksModel] |
2768 | + property var model: [] |
2769 | id: artistsTab |
2770 | objectName: "artiststab" |
2771 | anchors.fill: parent |
2772 | @@ -1092,10 +856,10 @@ |
2773 | |
2774 | // third tab is albums |
2775 | Tab { |
2776 | - property bool populated: false |
2777 | - property var loader: [albumModel.filterAlbums] |
2778 | + property bool populated: true |
2779 | + property var loader: [] |
2780 | property bool loading: false |
2781 | - property var model: [albumModel, albumTracksModel] |
2782 | + property var model: [] |
2783 | id: albumsTab |
2784 | objectName: "albumstab" |
2785 | anchors.fill: parent |
2786 | @@ -1109,10 +873,10 @@ |
2787 | |
2788 | // fourth tab is all songs |
2789 | Tab { |
2790 | - property bool populated: false |
2791 | - property var loader: [libraryModel.populate] |
2792 | + property bool populated: true |
2793 | + property var loader: [] |
2794 | property bool loading: false |
2795 | - property var model: [libraryModel] |
2796 | + property var model: [] |
2797 | id: tracksTab |
2798 | objectName: "trackstab" |
2799 | anchors.fill: parent |
2800 | @@ -1158,7 +922,7 @@ |
2801 | { |
2802 | allowLoading(selectedTab, true); // allow loading of the models |
2803 | |
2804 | - if (!selectedTab.populated && !selectedTab.loading && griloModel.loaded) { |
2805 | + if (!selectedTab.populated && !selectedTab.loading && loadedUI) { |
2806 | loading.visible = true |
2807 | selectedTab.loading = true |
2808 | |
2809 | |
2810 | === modified file 'playlists.js' |
2811 | --- playlists.js 2014-03-26 12:16:43 +0000 |
2812 | +++ playlists.js 2014-06-19 01:49:30 +0000 |
2813 | @@ -182,12 +182,11 @@ |
2814 | for(var i = 0; i < rs.rows.length; i++) { |
2815 | var dbItem = rs.rows.item(i); |
2816 | //console.log("Cover: "+ dbItem.cover); |
2817 | - res[i] = {'file': dbItem.track, |
2818 | + res[i] = {'filename': dbItem.track, |
2819 | 'title': dbItem.title, |
2820 | - 'artist': dbItem.artist, |
2821 | + 'author': dbItem.artist, |
2822 | 'album': dbItem.album, |
2823 | - 'cover': dbItem.cover, |
2824 | - 'year': dbItem.year, |
2825 | + 'date': dbItem.year, |
2826 | 'number': dbItem.number, |
2827 | 'length': dbItem.length, |
2828 | 'genre': dbItem.genre, |
2829 | @@ -227,10 +226,10 @@ |
2830 | // Get a list of unique covers for the playlist |
2831 | try { |
2832 | db.transaction(function(tx) { |
2833 | - var rs = tx.executeSql("SELECT * FROM playlist WHERE playlist=? AND cover <> '' ;", [playlist]); |
2834 | + var rs = tx.executeSql("SELECT * FROM playlist WHERE playlist=?;", [playlist]); |
2835 | for(var i = 0; i < rs.rows.length; i++) { |
2836 | - if (res.indexOf(rs.rows.item(i).cover) === -1) { |
2837 | - res.push(rs.rows.item(i).cover); |
2838 | + if (res.indexOf({author: rs.rows.item(i).artist, album: rs.rows.item(i).album}) === -1) { |
2839 | + res.push({author: rs.rows.item(i).artist, album: rs.rows.item(i).album}); |
2840 | } |
2841 | } |
2842 | }) |
2843 | |
2844 | === removed file 'plugins.json' |
2845 | --- plugins.json 2014-03-14 00:03:53 +0000 |
2846 | +++ plugins.json 1970-01-01 00:00:00 +0000 |
2847 | @@ -1,5 +0,0 @@ |
2848 | -[ |
2849 | -{ |
2850 | - "package": "qtdeclarative5-qtgrilo0.1" |
2851 | -} |
2852 | -] |
2853 | |
2854 | === modified file 'po/com.ubuntu.music.pot' |
2855 | --- po/com.ubuntu.music.pot 2014-06-06 11:35:53 +0000 |
2856 | +++ po/com.ubuntu.music.pot 2014-06-19 01:49:30 +0000 |
2857 | @@ -8,7 +8,7 @@ |
2858 | msgstr "" |
2859 | "Project-Id-Version: music-app\n" |
2860 | "Report-Msgid-Bugs-To: \n" |
2861 | -"POT-Creation-Date: 2014-06-06 12:31+0100\n" |
2862 | +"POT-Creation-Date: 2014-06-17 13:05-0400\n" |
2863 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
2864 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
2865 | "Language-Team: LANGUAGE <LL@li.org>\n" |
2866 | @@ -18,115 +18,115 @@ |
2867 | "Content-Transfer-Encoding: 8bit\n" |
2868 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" |
2869 | |
2870 | -#: ../LoginLastFM.qml:50 ../MusicSettings.qml:145 ../MusicSettings.qml:153 |
2871 | +#: ../LoginLastFM.qml:49 ../MusicSettings.qml:145 ../MusicSettings.qml:153 |
2872 | msgid "Last.fm" |
2873 | msgstr "" |
2874 | |
2875 | -#: ../LoginLastFM.qml:56 |
2876 | +#: ../LoginLastFM.qml:55 |
2877 | msgid "Login to be able to scrobble." |
2878 | msgstr "" |
2879 | |
2880 | -#: ../LoginLastFM.qml:64 |
2881 | +#: ../LoginLastFM.qml:63 |
2882 | msgid "Username" |
2883 | msgstr "" |
2884 | |
2885 | -#: ../LoginLastFM.qml:74 |
2886 | +#: ../LoginLastFM.qml:73 |
2887 | msgid "Password" |
2888 | msgstr "" |
2889 | |
2890 | -#: ../LoginLastFM.qml:96 |
2891 | +#: ../LoginLastFM.qml:95 |
2892 | msgid "Login" |
2893 | msgstr "" |
2894 | |
2895 | -#: ../LoginLastFM.qml:103 |
2896 | +#: ../LoginLastFM.qml:102 |
2897 | msgid "Trying to login..." |
2898 | msgstr "" |
2899 | |
2900 | -#: ../LoginLastFM.qml:117 |
2901 | +#: ../LoginLastFM.qml:116 |
2902 | msgid "Login Successful" |
2903 | msgstr "" |
2904 | |
2905 | -#: ../LoginLastFM.qml:123 |
2906 | +#: ../LoginLastFM.qml:122 |
2907 | msgid "Login Failed" |
2908 | msgstr "" |
2909 | |
2910 | -#: ../LoginLastFM.qml:129 |
2911 | +#: ../LoginLastFM.qml:128 |
2912 | msgid "You forgot to set your username and/or password" |
2913 | msgstr "" |
2914 | |
2915 | -#: ../MusicAlbums.qml:33 ../MusicStart.qml:333 |
2916 | +#: ../MusicAlbums.qml:37 ../MusicStart.qml:370 |
2917 | msgid "Albums" |
2918 | msgstr "" |
2919 | |
2920 | -#: ../MusicArtists.qml:33 |
2921 | +#: ../MusicArtists.qml:37 |
2922 | msgid "Artists" |
2923 | msgstr "" |
2924 | |
2925 | -#: ../MusicArtists.qml:107 ../common/AlbumsSheet.qml:116 |
2926 | +#: ../MusicArtists.qml:153 ../common/AlbumsSheet.qml:124 |
2927 | #, qt-format |
2928 | msgid "%1 album" |
2929 | msgid_plural "%1 albums" |
2930 | msgstr[0] "" |
2931 | msgstr[1] "" |
2932 | |
2933 | -#: ../MusicArtists.qml:124 ../MusicPlaylists.qml:186 ../MusicStart.qml:314 |
2934 | -#: ../common/SongsSheet.qml:129 |
2935 | +#: ../MusicArtists.qml:170 ../MusicPlaylists.qml:187 ../MusicStart.qml:351 |
2936 | +#: ../common/SongsSheet.qml:144 |
2937 | #, qt-format |
2938 | msgid "%1 song" |
2939 | msgid_plural "%1 songs" |
2940 | msgstr[0] "" |
2941 | msgstr[1] "" |
2942 | |
2943 | -#: ../MusicNowPlaying.qml:33 |
2944 | +#: ../MusicNowPlaying.qml:34 |
2945 | msgid "Now Playing" |
2946 | msgstr "" |
2947 | |
2948 | #. TRANSLATORS: this is the name of the playlists page shown in the tab header. |
2949 | #. Remember to keep the translation short to fit the screen width |
2950 | -#: ../MusicPlaylists.qml:38 |
2951 | +#: ../MusicPlaylists.qml:39 |
2952 | msgid "Playlists" |
2953 | msgstr "" |
2954 | |
2955 | #. TRANSLATORS: this is a title of a dialog with a prompt to rename a playlist |
2956 | -#: ../MusicPlaylists.qml:59 |
2957 | +#: ../MusicPlaylists.qml:60 |
2958 | msgid "Change name" |
2959 | msgstr "" |
2960 | |
2961 | -#: ../MusicPlaylists.qml:60 |
2962 | +#: ../MusicPlaylists.qml:61 |
2963 | msgid "Enter the new name of the playlist." |
2964 | msgstr "" |
2965 | |
2966 | -#: ../MusicPlaylists.qml:71 |
2967 | +#: ../MusicPlaylists.qml:72 |
2968 | msgid "Change" |
2969 | msgstr "" |
2970 | |
2971 | -#: ../MusicPlaylists.qml:84 |
2972 | +#: ../MusicPlaylists.qml:85 |
2973 | msgid "You didn't type in a name." |
2974 | msgstr "" |
2975 | |
2976 | -#: ../MusicPlaylists.qml:89 ../MusicPlaylists.qml:115 ../music-app.qml:987 |
2977 | +#: ../MusicPlaylists.qml:90 ../MusicPlaylists.qml:116 ../music-app.qml:752 |
2978 | msgid "Cancel" |
2979 | msgstr "" |
2980 | |
2981 | #. TRANSLATORS: this is a title of a dialog with a prompt to delete a playlist |
2982 | -#: ../MusicPlaylists.qml:102 |
2983 | +#: ../MusicPlaylists.qml:103 |
2984 | msgid "Are you sure?" |
2985 | msgstr "" |
2986 | |
2987 | -#: ../MusicPlaylists.qml:103 |
2988 | +#: ../MusicPlaylists.qml:104 |
2989 | msgid "This will delete your playlist." |
2990 | msgstr "" |
2991 | |
2992 | -#: ../MusicPlaylists.qml:106 |
2993 | +#: ../MusicPlaylists.qml:107 |
2994 | msgid "Remove" |
2995 | msgstr "" |
2996 | |
2997 | -#: ../MusicSearch.qml:42 ../MusicToolbar.qml:508 ../music-app.qml:93 |
2998 | -#: ../music-app.qml:141 ../music-app.qml:147 |
2999 | +#: ../MusicSearch.qml:44 ../MusicToolbar.qml:508 ../music-app.qml:94 |
3000 | +#: ../music-app.qml:142 ../music-app.qml:148 |
3001 | msgid "Search" |
3002 | msgstr "" |
3003 | |
3004 | -#: ../MusicSettings.qml:30 ../music-app.qml:191 |
3005 | +#: ../MusicSettings.qml:30 ../music-app.qml:192 |
3006 | msgid "Settings" |
3007 | msgstr "" |
3008 | |
3009 | @@ -212,20 +212,20 @@ |
3010 | msgid "Clean everything!" |
3011 | msgstr "" |
3012 | |
3013 | -#: ../MusicStart.qml:33 ../music-app.qml:366 ../music-app.qml:1002 |
3014 | +#: ../MusicStart.qml:37 ../music-app.qml:373 ../music-app.qml:767 |
3015 | #: com.ubuntu.music_music.desktop.in.in.h:1 |
3016 | msgid "Music" |
3017 | msgstr "" |
3018 | |
3019 | -#: ../MusicStart.qml:80 |
3020 | +#: ../MusicStart.qml:84 |
3021 | msgid "Recent" |
3022 | msgstr "" |
3023 | |
3024 | -#: ../MusicStart.qml:108 |
3025 | +#: ../MusicStart.qml:112 |
3026 | msgid "Clear History" |
3027 | msgstr "" |
3028 | |
3029 | -#: ../MusicStart.qml:217 |
3030 | +#: ../MusicStart.qml:222 |
3031 | msgid "Genres" |
3032 | msgstr "" |
3033 | |
3034 | @@ -237,38 +237,38 @@ |
3035 | msgid "Tap play or any item to start" |
3036 | msgstr "" |
3037 | |
3038 | -#: ../MusicTracks.qml:33 |
3039 | +#: ../MusicTracks.qml:37 |
3040 | msgid "Songs" |
3041 | msgstr "" |
3042 | |
3043 | -#: ../MusicaddtoPlaylist.qml:38 ../common/ExpanderItems/AddToPlaylist.qml:59 |
3044 | -#: ../music-app.qml:934 |
3045 | +#: ../MusicaddtoPlaylist.qml:39 ../common/ExpanderItems/AddToPlaylist.qml:59 |
3046 | +#: ../music-app.qml:699 |
3047 | msgid "Select playlist" |
3048 | msgstr "" |
3049 | |
3050 | -#: ../MusicaddtoPlaylist.qml:130 |
3051 | +#: ../MusicaddtoPlaylist.qml:131 |
3052 | msgid "New playlist" |
3053 | msgstr "" |
3054 | |
3055 | -#: ../common/AlbumsSheet.qml:163 ../common/AlbumsSheet.qml:351 |
3056 | -#: ../common/SongsSheet.qml:158 |
3057 | +#: ../common/AlbumsSheet.qml:180 ../common/AlbumsSheet.qml:382 |
3058 | +#: ../common/SongsSheet.qml:173 |
3059 | msgid "Play all" |
3060 | msgstr "" |
3061 | |
3062 | -#: ../common/AlbumsSheet.qml:214 ../common/AlbumsSheet.qml:399 |
3063 | -#: ../common/ExpanderItems/AddToQueue.qml:45 ../common/SongsSheet.qml:209 |
3064 | -#: ../music-app.qml:909 |
3065 | +#: ../common/AlbumsSheet.qml:228 ../common/AlbumsSheet.qml:427 |
3066 | +#: ../common/ExpanderItems/AddToQueue.qml:45 ../common/SongsSheet.qml:225 |
3067 | +#: ../music-app.qml:674 |
3068 | msgid "Add to queue" |
3069 | msgstr "" |
3070 | |
3071 | -#: ../common/AlbumsSheet.qml:323 ../common/SongsSheet.qml:128 |
3072 | +#: ../common/AlbumsSheet.qml:352 ../common/SongsSheet.qml:143 |
3073 | #, qt-format |
3074 | msgid " | %1 song" |
3075 | msgid_plural " | %1 songs" |
3076 | msgstr[0] "" |
3077 | msgstr[1] "" |
3078 | |
3079 | -#: ../common/ExpanderItems/AddToPlaylist.qml:47 ../music-app.qml:923 |
3080 | +#: ../common/ExpanderItems/AddToPlaylist.qml:47 ../music-app.qml:688 |
3081 | msgid "Add to playlist" |
3082 | msgstr "" |
3083 | |
3084 | @@ -290,112 +290,104 @@ |
3085 | msgid "Clear" |
3086 | msgstr "" |
3087 | |
3088 | -#: ../meta-database.js:444 ../meta-database.js:447 ../music-app.qml:695 |
3089 | +#: ../meta-database.js:90 ../meta-database.js:92 |
3090 | msgid "Unknown Album" |
3091 | msgstr "" |
3092 | |
3093 | -#: ../meta-database.js:445 ../music-app.qml:694 |
3094 | +#: ../meta-database.js:91 |
3095 | msgid "Unknown Artist" |
3096 | msgstr "" |
3097 | |
3098 | -#: ../music-app.qml:142 |
3099 | +#: ../music-app.qml:143 |
3100 | msgid "Search Track" |
3101 | msgstr "" |
3102 | |
3103 | -#: ../music-app.qml:154 |
3104 | +#: ../music-app.qml:155 |
3105 | msgid "Next" |
3106 | msgstr "" |
3107 | |
3108 | -#: ../music-app.qml:155 |
3109 | +#: ../music-app.qml:156 |
3110 | msgid "Next Track" |
3111 | msgstr "" |
3112 | |
3113 | -#: ../music-app.qml:161 |
3114 | +#: ../music-app.qml:162 |
3115 | msgid "Pause" |
3116 | msgstr "" |
3117 | |
3118 | -#: ../music-app.qml:161 |
3119 | +#: ../music-app.qml:162 |
3120 | msgid "Play" |
3121 | msgstr "" |
3122 | |
3123 | -#: ../music-app.qml:163 |
3124 | +#: ../music-app.qml:164 |
3125 | msgid "Pause Playback" |
3126 | msgstr "" |
3127 | |
3128 | -#: ../music-app.qml:163 |
3129 | +#: ../music-app.qml:164 |
3130 | msgid "Continue or start playback" |
3131 | msgstr "" |
3132 | |
3133 | -#: ../music-app.qml:168 |
3134 | +#: ../music-app.qml:169 |
3135 | msgid "Back" |
3136 | msgstr "" |
3137 | |
3138 | -#: ../music-app.qml:169 |
3139 | +#: ../music-app.qml:170 |
3140 | msgid "Go back to last page" |
3141 | msgstr "" |
3142 | |
3143 | -#: ../music-app.qml:177 |
3144 | +#: ../music-app.qml:178 |
3145 | msgid "Previous" |
3146 | msgstr "" |
3147 | |
3148 | -#: ../music-app.qml:178 |
3149 | +#: ../music-app.qml:179 |
3150 | msgid "Previous Track" |
3151 | msgstr "" |
3152 | |
3153 | -#: ../music-app.qml:183 |
3154 | +#: ../music-app.qml:184 |
3155 | msgid "Stop" |
3156 | msgstr "" |
3157 | |
3158 | -#: ../music-app.qml:184 |
3159 | +#: ../music-app.qml:185 |
3160 | msgid "Stop Playback" |
3161 | msgstr "" |
3162 | |
3163 | -#: ../music-app.qml:192 |
3164 | +#: ../music-app.qml:193 |
3165 | msgid "Music Settings" |
3166 | msgstr "" |
3167 | |
3168 | #. TRANSLATORS: this refers to a number of songs greater than one. The actual number will be prepended to the string automatically (plural forms are not yet fully supported in usermetrics, the library that displays that string) |
3169 | -#: ../music-app.qml:294 |
3170 | +#: ../music-app.qml:288 |
3171 | msgid "songs played today" |
3172 | msgstr "" |
3173 | |
3174 | -#: ../music-app.qml:295 |
3175 | +#: ../music-app.qml:289 |
3176 | msgid "No songs played today" |
3177 | msgstr "" |
3178 | |
3179 | -#: ../music-app.qml:392 |
3180 | +#: ../music-app.qml:396 |
3181 | msgid "Debug: " |
3182 | msgstr "" |
3183 | |
3184 | -#: ../music-app.qml:701 |
3185 | -msgid "Unknown Year" |
3186 | -msgstr "" |
3187 | - |
3188 | -#: ../music-app.qml:702 |
3189 | -msgid "Unknown Genre" |
3190 | -msgstr "" |
3191 | - |
3192 | -#: ../music-app.qml:947 |
3193 | +#: ../music-app.qml:712 |
3194 | msgid "New Playlist" |
3195 | msgstr "" |
3196 | |
3197 | -#: ../music-app.qml:948 |
3198 | +#: ../music-app.qml:713 |
3199 | msgid "Name your playlist." |
3200 | msgstr "" |
3201 | |
3202 | -#: ../music-app.qml:952 |
3203 | +#: ../music-app.qml:717 |
3204 | msgid "Name" |
3205 | msgstr "" |
3206 | |
3207 | -#: ../music-app.qml:960 |
3208 | +#: ../music-app.qml:725 |
3209 | msgid "Create" |
3210 | msgstr "" |
3211 | |
3212 | -#: ../music-app.qml:976 |
3213 | +#: ../music-app.qml:741 |
3214 | msgid "Error: " |
3215 | msgstr "" |
3216 | |
3217 | -#: ../music-app.qml:981 |
3218 | +#: ../music-app.qml:746 |
3219 | msgid "Error: You didn't type a name." |
3220 | msgstr "" |
3221 | |
3222 | |
3223 | === modified file 'po/lv.po' |
3224 | --- po/lv.po 2014-06-07 06:34:52 +0000 |
3225 | +++ po/lv.po 2014-06-19 01:49:30 +0000 |
3226 | @@ -6,11 +6,12 @@ |
3227 | msgid "" |
3228 | msgstr "" |
3229 | "Project-Id-Version: music-app\n" |
3230 | -"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" |
3231 | +"Report-Msgid-Bugs-To: \n" |
3232 | "POT-Creation-Date: 2014-06-06 12:31+0100\n" |
3233 | "PO-Revision-Date: 2014-06-06 17:55+0000\n" |
3234 | "Last-Translator: Jānis-Marks Gailis <jeanmarc.gailis@gmail.com>\n" |
3235 | "Language-Team: Latvian <lv@li.org>\n" |
3236 | +"Language: lv\n" |
3237 | "MIME-Version: 1.0\n" |
3238 | "Content-Type: text/plain; charset=UTF-8\n" |
3239 | "Content-Transfer-Encoding: 8bit\n" |
3240 | |
3241 | === modified file 'tests/autopilot/music_app/__init__.py' |
3242 | --- tests/autopilot/music_app/__init__.py 2013-06-21 23:06:10 +0000 |
3243 | +++ tests/autopilot/music_app/__init__.py 2014-06-19 01:49:30 +0000 |
3244 | @@ -1,5 +1,5 @@ |
3245 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3246 | -# Copyright 2013 Canonical |
3247 | +# Copyright 2013, 2014 Canonical |
3248 | # |
3249 | # This program is free software: you can redistribute it and/or modify it |
3250 | # under the terms of the GNU General Public License version 3, as published |
3251 | |
3252 | === modified file 'tests/autopilot/music_app/content/1.ogg' |
3253 | Binary files tests/autopilot/music_app/content/1.ogg 2013-09-27 15:14:10 +0000 and tests/autopilot/music_app/content/1.ogg 2014-06-19 01:49:30 +0000 differ |
3254 | === removed directory 'tests/autopilot/music_app/content/mediascanner' |
3255 | === added directory 'tests/autopilot/music_app/content/mediascanner-2.0' |
3256 | === added file 'tests/autopilot/music_app/content/mediascanner-2.0/mediastore.db' |
3257 | Binary files tests/autopilot/music_app/content/mediascanner-2.0/mediastore.db 1970-01-01 00:00:00 +0000 and tests/autopilot/music_app/content/mediascanner-2.0/mediastore.db 2014-06-19 01:49:30 +0000 differ |
3258 | === added file 'tests/autopilot/music_app/content/mediascanner-2.0/mediastore.sql' |
3259 | --- tests/autopilot/music_app/content/mediascanner-2.0/mediastore.sql 1970-01-01 00:00:00 +0000 |
3260 | +++ tests/autopilot/music_app/content/mediascanner-2.0/mediastore.sql 2014-06-19 01:49:30 +0000 |
3261 | @@ -0,0 +1,39 @@ |
3262 | +BEGIN TRANSACTION; |
3263 | +DROP TABLE media; |
3264 | +CREATE TABLE media ( |
3265 | + filename TEXT PRIMARY KEY NOT NULL, |
3266 | + content_type TEXT, |
3267 | + etag TEXT, |
3268 | + title TEXT, |
3269 | + date TEXT, |
3270 | + artist TEXT, -- Only relevant to audio |
3271 | + album TEXT, -- Only relevant to audio |
3272 | + album_artist TEXT, -- Only relevant to audio |
3273 | + genre TEXT, -- Only relevant to audio |
3274 | + disc_number INTEGER, -- Only relevant to audio |
3275 | + track_number INTEGER, -- Only relevant to audio |
3276 | + duration INTEGER, |
3277 | + width INTEGER, -- Only relevant to video/images |
3278 | + height INTEGER, -- Only relevant to video/images |
3279 | + latitude DOUBLE, |
3280 | + longitude DOUBLE, |
3281 | + type INTEGER -- 0=Audio, 1=Video |
3282 | +); |
3283 | +INSERT INTO "media" VALUES('/home/phablet/Music/1.ogg','audio/ogg','1401368666:257952','Gran Vals','1902','Francisco Tárrega','','Francisco Tárrega','',0,0,202,0,0,0.0,0.0,1); |
3284 | +INSERT INTO "media" VALUES('/home/phablet/Music/2.ogg','audio/ogg','1401457265:78191','Swansong','','Josh Woodward','','Josh Woodward','',0,0,62,0,0,0.0,0.0,1); |
3285 | +INSERT INTO "media" VALUES('/home/phablet/Music/3.mp3','audio/mpeg','1401457265:78191','TestMP3Title','','TestMP3Artist','TestMP3Album','TestMP3Artist','',0,0,6,0,0,0.0,0.0,1); |
3286 | + |
3287 | +CREATE INDEX media_album_album_artist_idx ON media(album, album_artist); |
3288 | +CREATE TRIGGER media_ai AFTER INSERT ON media BEGIN |
3289 | + INSERT INTO media_fts(docid, title, artist, album) VALUES (new.rowid, new.title, new.artist, new.album); |
3290 | +END; |
3291 | +CREATE TRIGGER media_au AFTER UPDATE ON media BEGIN |
3292 | + INSERT INTO media_fts(docid, title, artist, album) VALUES (new.rowid, new.title, new.artist, new.album); |
3293 | +END; |
3294 | +CREATE TRIGGER media_bd BEFORE DELETE ON media BEGIN |
3295 | + DELETE FROM media_fts WHERE docid=old.rowid; |
3296 | +END; |
3297 | +CREATE TRIGGER media_bu BEFORE UPDATE ON media BEGIN |
3298 | + DELETE FROM media_fts WHERE docid=old.rowid; |
3299 | +END; |
3300 | +COMMIT; |
3301 | |
3302 | === removed directory 'tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab' |
3303 | === removed file 'tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments.gen' |
3304 | Binary files tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments.gen 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments.gen 1970-01-01 00:00:00 +0000 differ |
3305 | === removed file 'tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments_1' |
3306 | Binary files tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments_1 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/segments_1 1970-01-01 00:00:00 +0000 differ |
3307 | === removed file 'tests/autopilot/music_app/content/mediascanner/7d246d8c-5e6d-4fe8-8271-1472eb02c3ab/write.lock' |
3308 | === removed directory 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7' |
3309 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_0.cfs' |
3310 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_0.cfs 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_0.cfs 1970-01-01 00:00:00 +0000 differ |
3311 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1.cfs' |
3312 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1.cfs 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1.cfs 1970-01-01 00:00:00 +0000 differ |
3313 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1_1.del' |
3314 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1_1.del 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_1_1.del 1970-01-01 00:00:00 +0000 differ |
3315 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_2.cfs' |
3316 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_2.cfs 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_2.cfs 1970-01-01 00:00:00 +0000 differ |
3317 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3.cfs' |
3318 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3.cfs 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3.cfs 1970-01-01 00:00:00 +0000 differ |
3319 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3_1.del' |
3320 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3_1.del 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_3_1.del 1970-01-01 00:00:00 +0000 differ |
3321 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_4.cfs' |
3322 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_4.cfs 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/_4.cfs 1970-01-01 00:00:00 +0000 differ |
3323 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments.gen' |
3324 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments.gen 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments.gen 1970-01-01 00:00:00 +0000 differ |
3325 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments_6' |
3326 | Binary files tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments_6 2013-10-15 18:19:36 +0000 and tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/segments_6 1970-01-01 00:00:00 +0000 differ |
3327 | === removed file 'tests/autopilot/music_app/content/mediascanner/d15682c3-89f1-4e41-abfc-531e4740e5a7/write.lock' |
3328 | === removed file 'tests/autopilot/music_app/content/mediascanner/mediaindex' |
3329 | --- tests/autopilot/music_app/content/mediascanner/mediaindex 2013-10-15 18:19:36 +0000 |
3330 | +++ tests/autopilot/music_app/content/mediascanner/mediaindex 1970-01-01 00:00:00 +0000 |
3331 | @@ -1,10 +0,0 @@ |
3332 | -[global] |
3333 | -format=Ubuntu Media Scanner Meta Index 1.0 |
3334 | - |
3335 | -[media:home/autopilot-music-app/Music] |
3336 | -segments=d15682c3-89f1-4e41-abfc-531e4740e5a7 |
3337 | -relative-path=home/autopilot-music-app/Music |
3338 | - |
3339 | -[media:] |
3340 | -segments=7d246d8c-5e6d-4fe8-8271-1472eb02c3ab |
3341 | -relative-path= |
3342 | |
3343 | === modified file 'tests/autopilot/music_app/emulators.py' |
3344 | --- tests/autopilot/music_app/emulators.py 2014-05-03 15:54:38 +0000 |
3345 | +++ tests/autopilot/music_app/emulators.py 2014-06-19 01:49:30 +0000 |
3346 | @@ -1,5 +1,5 @@ |
3347 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3348 | -# Copyright 2013 Canonical |
3349 | +# Copyright 2013, 2014 Canonical |
3350 | # |
3351 | # This program is free software: you can redistribute it and/or modify it |
3352 | # under the terms of the GNU General Public License version 3, as published |
3353 | @@ -51,6 +51,23 @@ |
3354 | |
3355 | self.pointing_device.drag(x1, y1, x1, y1 - toolbar.fullHeight) |
3356 | |
3357 | + def add_to_queue_from_albums_tab_album_sheet(self, artistName, trackTitle): |
3358 | + # switch to albums tab |
3359 | + self.switch_to_tab("albumstab") |
3360 | + |
3361 | + #select album |
3362 | + albumartist = self.get_albums_albumartist(artistName) |
3363 | + self.pointing_device.click_object(albumartist) |
3364 | + |
3365 | + #get track item to add to queue |
3366 | + trackicon = self.get_album_sheet_listview_trackicon( |
3367 | + trackTitle) |
3368 | + self.pointing_device.click_object(trackicon) |
3369 | + |
3370 | + #click on Add to queue |
3371 | + queueTrackLabel = self.get_album_sheet_queuetrack_label() |
3372 | + self.pointing_device.click_object(queueTrackLabel) |
3373 | + |
3374 | def get_player(self): |
3375 | return self.select_single("*", objectName="player") |
3376 | |
3377 | @@ -83,7 +100,9 @@ |
3378 | return self.wait_select_single("*", objectName="genreItemObject") |
3379 | |
3380 | def get_back_button(self): |
3381 | - return self.select_single("*", objectName="nowPlayingBackButtonObject") |
3382 | + backButton = self.select_single("AbstractButton", |
3383 | + objectName="backButton") |
3384 | + return backButton |
3385 | |
3386 | def get_albumstab(self): |
3387 | return self.select_single("Tab", objectName="albumstab") |
3388 | |
3389 | === modified file 'tests/autopilot/music_app/tests/__init__.py' |
3390 | --- tests/autopilot/music_app/tests/__init__.py 2014-04-30 15:24:44 +0000 |
3391 | +++ tests/autopilot/music_app/tests/__init__.py 2014-06-19 01:49:30 +0000 |
3392 | @@ -1,5 +1,5 @@ |
3393 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3394 | -# Copyright 2013 Canonical |
3395 | +# Copyright 2013, 2014 Canonical |
3396 | # |
3397 | # This program is free software: you can redistribute it and/or modify it |
3398 | # under the terms of the GNU General Public License version 3, as published |
3399 | @@ -7,28 +7,26 @@ |
3400 | |
3401 | """Music app autopilot tests.""" |
3402 | |
3403 | -import tempfile |
3404 | -try: |
3405 | - from unittest import mock |
3406 | -except ImportError: |
3407 | - import mock |
3408 | import os |
3409 | +import subprocess |
3410 | import os.path |
3411 | import shutil |
3412 | -#import subprocess |
3413 | +import sqlite3 |
3414 | import logging |
3415 | import music_app |
3416 | |
3417 | +import fixtures |
3418 | +from music_app import emulators |
3419 | + |
3420 | +from autopilot import logging as autopilot_logging |
3421 | from autopilot.input import Mouse, Touch, Pointer |
3422 | from autopilot.platform import model |
3423 | from autopilot.testcase import AutopilotTestCase |
3424 | |
3425 | -from music_app import emulators |
3426 | - |
3427 | from ubuntuuitoolkit import ( |
3428 | base, |
3429 | emulators as toolkit_emulators, |
3430 | - environment |
3431 | + fixture_setup as toolkit_fixtures |
3432 | ) |
3433 | |
3434 | |
3435 | @@ -50,6 +48,8 @@ |
3436 | local_location_dir = os.path.dirname(os.path.dirname(working_dir)) |
3437 | local_location = local_location_dir + "/music-app.qml" |
3438 | installed_location = "/usr/share/music-app/music-app.qml" |
3439 | + backup_root = os.path.join( |
3440 | + os.path.expanduser('~'), '.local/share/com.ubuntu.music/backups') |
3441 | |
3442 | def setup_environment(self): |
3443 | if os.path.exists(self.local_location): |
3444 | @@ -64,67 +64,199 @@ |
3445 | return launch, test_type |
3446 | |
3447 | def setUp(self): |
3448 | + subprocess.call(["stop", "mediascanner-2.0"]) |
3449 | + |
3450 | + try: |
3451 | + pid = subprocess.check_output(["pidof", "mediascanner-dbus-2.0"]) |
3452 | + except subprocess.CalledProcessError: |
3453 | + logger.debug("mediascanner-dbus-2.0 not running") |
3454 | + else: |
3455 | + pid = pid.decode("utf-8") |
3456 | + pid = pid.split(None, 1)[0] |
3457 | + subprocess.call(["kill", "-9", pid]) |
3458 | + |
3459 | + # Stop any mediascanner-dbus and restart mediascanner on exit |
3460 | + self.addCleanup(subprocess.call, |
3461 | + 'kill -9 \ |
3462 | + `pidof \ |
3463 | + /usr/lib/*/mediascanner-2.0/mediascanner-dbus-2.0`', |
3464 | + shell=True) |
3465 | + self.addCleanup(subprocess.call, ["start", "mediascanner-2.0"]) |
3466 | + |
3467 | launch, self.test_type = self.setup_environment() |
3468 | - self.home_dir = self._patch_home() |
3469 | + |
3470 | + #Use backup and restore to setup test environment |
3471 | + ################################################# |
3472 | + #for now, we will use real /home |
3473 | + logger.debug("Backup root folder %s" % self.backup_root) |
3474 | + |
3475 | + #backup and wipe before testing |
3476 | + sqlite_dir = os.path.join( |
3477 | + os.environ.get('HOME'), '.local/share/com.ubuntu.music/Databases') |
3478 | + self.backup_folder(sqlite_dir) |
3479 | + self.addCleanup(lambda: self.restore_folder(sqlite_dir)) |
3480 | + |
3481 | + #backup Music folder and restore it after testing |
3482 | + self.backup_folder(os.path.join(os.environ.get('HOME'), 'Music')) |
3483 | + self.addCleanup(lambda: self.restore_folder( |
3484 | + os.path.join(os.environ.get('HOME'), 'Music'))) |
3485 | + |
3486 | + #backup mediascanner folder and restore it after testing |
3487 | + self.backup_folder(os.path.join(os.environ.get('HOME'), |
3488 | + '.cache/mediascanner-2.0')) |
3489 | + self.addCleanup(lambda: self.restore_folder(os.path.join( |
3490 | + os.environ.get('HOME'), |
3491 | + '.cache/mediascanner-2.0'))) |
3492 | + |
3493 | + self.home_dir = os.environ['HOME'] |
3494 | self._create_music_library() |
3495 | + ################################################# |
3496 | + #Use backup and restore to setup test environment |
3497 | + |
3498 | + #Use mocking fakehome |
3499 | + ##################### |
3500 | + #self.home_dir = self._patch_home() |
3501 | + |
3502 | + #self._create_music_library() |
3503 | + |
3504 | + ##we need to also tell upstart about our fake home |
3505 | + ##and we need to do this all in one shell, |
3506 | + ##also passing along our fake env (env=env) |
3507 | + #logger.debug("Launching mediascanner") |
3508 | + #env = os.environ.copy() |
3509 | + #sethome = "initctl set-env HOME=" + self.home_dir |
3510 | + #retcode = subprocess.check_output(sethome + "; \ |
3511 | + #start mediascanner-2.0", |
3512 | + #env=env, |
3513 | + #stderr=subprocess.STDOUT, |
3514 | + #shell=True) |
3515 | + #logger.debug("mediascanner launched %s" % retcode) |
3516 | + #time.sleep(10) |
3517 | + |
3518 | + #logger.debug("Launching mediascanner-dbus") |
3519 | + #retcode = subprocess.call( |
3520 | + #"/usr/lib/*/mediascanner-2.0/mediascanner-dbus-2.0 &", |
3521 | + #env=env, stderr=subprocess.STDOUT, shell=True) |
3522 | + #logger.debug("mediascanner-dbus launched %s" % retcode) |
3523 | + |
3524 | + ##we attempt to reset home for future upstart jobs |
3525 | + #retcode = subprocess.check_output("initctl reset-env", |
3526 | + #env=env, shell=True) |
3527 | + #retcode = subprocess.check_output("initctl get-env HOME", |
3528 | + #env=env, shell=True) |
3529 | + #logger.debug("reset initctl home %s" % retcode) |
3530 | + ##################### |
3531 | + #Use mocking fakehome |
3532 | + |
3533 | self.pointing_device = Pointer(self.input_device_class.create()) |
3534 | super(MusicTestCase, self).setUp() |
3535 | launch() |
3536 | |
3537 | + @autopilot_logging.log_action(logger.info) |
3538 | def launch_test_local(self): |
3539 | - logger.debug("Running via local installation") |
3540 | self.app = self.launch_test_application( |
3541 | base.get_qmlscene_launch_command(), |
3542 | self.local_location, |
3543 | + "debug", |
3544 | app_type='qt', |
3545 | emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
3546 | |
3547 | + @autopilot_logging.log_action(logger.info) |
3548 | def launch_test_installed(self): |
3549 | - logger.debug("Running via installed debian package") |
3550 | self.app = self.launch_test_application( |
3551 | base.get_qmlscene_launch_command(), |
3552 | self.installed_location, |
3553 | + "debug", |
3554 | app_type='qt', |
3555 | emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
3556 | |
3557 | + @autopilot_logging.log_action(logger.info) |
3558 | def launch_test_click(self): |
3559 | - logger.debug("Running via click package") |
3560 | self.app = self.launch_click_package( |
3561 | "com.ubuntu.music", |
3562 | emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
3563 | |
3564 | - def _patch_home(self): |
3565 | - #make a temp dir |
3566 | - temp_dir = tempfile.mkdtemp() |
3567 | - |
3568 | - #delete it, and recreate it to the length |
3569 | - #required so our patching the db works |
3570 | - #require a length of 25 |
3571 | - shutil.rmtree(temp_dir) |
3572 | - temp_dir = temp_dir.ljust(25, 'X') |
3573 | - os.mkdir(temp_dir) |
3574 | - logger.debug("Created fake home directory " + temp_dir) |
3575 | - self.addCleanup(shutil.rmtree, temp_dir) |
3576 | - |
3577 | - #if the Xauthority file is in home directory |
3578 | - #make sure we copy it to temp home, otherwise do nothing |
3579 | - xauth = os.path.expanduser(os.path.join('~', '.Xauthority')) |
3580 | + def _copy_xauthority_file(self, directory): |
3581 | + """ Copy .Xauthority file to directory, if it exists in /home |
3582 | + """ |
3583 | + #If running under xvfb, as jenkins does, |
3584 | + #xsession will fail to start without xauthority file |
3585 | + #Thus if the Xauthority file is in the home directory |
3586 | + #make sure we copy it to our temp home directory |
3587 | + |
3588 | + xauth = os.path.expanduser(os.path.join(os.environ.get('HOME'), |
3589 | + '.Xauthority')) |
3590 | if os.path.isfile(xauth): |
3591 | - logger.debug("Copying .Xauthority to fake home " + temp_dir) |
3592 | + logger.debug("Copying .Xauthority to %s" % directory) |
3593 | shutil.copyfile( |
3594 | - os.path.expanduser(os.path.join('~', '.Xauthority')), |
3595 | - os.path.join(temp_dir, '.Xauthority')) |
3596 | + os.path.expanduser(os.path.join(os.environ.get('HOME'), |
3597 | + '.Xauthority')), |
3598 | + os.path.join(directory, '.Xauthority')) |
3599 | |
3600 | - #click can use initctl env (upstart), but desktop still requires mock |
3601 | + def _patch_home(self): |
3602 | + """ mock /home for testing purposes to preserve user data |
3603 | + """ |
3604 | + #click requires apparmor profile, and writing to special dir |
3605 | + #but the desktop can write to a traditional /tmp directory |
3606 | if self.test_type == 'click': |
3607 | - environment.set_initctl_env_var('HOME', temp_dir) |
3608 | - self.addCleanup(environment.unset_initctl_env_var, 'HOME') |
3609 | + env_dir = os.path.join(os.environ.get('HOME'), 'autopilot', |
3610 | + 'fakeenv') |
3611 | + |
3612 | + if not os.path.exists(env_dir): |
3613 | + os.makedirs(env_dir) |
3614 | + |
3615 | + temp_dir_fixture = fixtures.TempDir(env_dir) |
3616 | + self.useFixture(temp_dir_fixture) |
3617 | + |
3618 | + #apparmor doesn't allow the app to create needed directories, |
3619 | + #so we create them now |
3620 | + temp_dir = temp_dir_fixture.path |
3621 | + temp_dir_cache = os.path.join(temp_dir, '.cache') |
3622 | + temp_dir_cache_font = os.path.join(temp_dir_cache, 'fontconfig') |
3623 | + temp_dir_cache_media = os.path.join(temp_dir_cache, 'media-art') |
3624 | + temp_dir_cache_write = os.path.join(temp_dir_cache, |
3625 | + 'tncache-write-text.null') |
3626 | + temp_dir_config = os.path.join(temp_dir, '.config') |
3627 | + temp_dir_toolkit = os.path.join(temp_dir_config, |
3628 | + 'ubuntu-ui-toolkit') |
3629 | + temp_dir_font = os.path.join(temp_dir_cache, '.fontconfig') |
3630 | + temp_dir_local = os.path.join(temp_dir, '.local', 'share') |
3631 | + temp_dir_confined = os.path.join(temp_dir, 'confined') |
3632 | + |
3633 | + if not os.path.exists(temp_dir_cache): |
3634 | + os.makedirs(temp_dir_cache) |
3635 | + if not os.path.exists(temp_dir_cache_font): |
3636 | + os.makedirs(temp_dir_cache_font) |
3637 | + if not os.path.exists(temp_dir_cache_media): |
3638 | + os.makedirs(temp_dir_cache_media) |
3639 | + if not os.path.exists(temp_dir_cache_write): |
3640 | + os.makedirs(temp_dir_cache_write) |
3641 | + if not os.path.exists(temp_dir_config): |
3642 | + os.makedirs(temp_dir_config) |
3643 | + if not os.path.exists(temp_dir_toolkit): |
3644 | + os.makedirs(temp_dir_toolkit) |
3645 | + if not os.path.exists(temp_dir_font): |
3646 | + os.makedirs(temp_dir_font) |
3647 | + if not os.path.exists(temp_dir_local): |
3648 | + os.makedirs(temp_dir_local) |
3649 | + if not os.path.exists(temp_dir_confined): |
3650 | + os.makedirs(temp_dir_confined) |
3651 | + |
3652 | + #before we set fixture, copy xauthority if needed |
3653 | + self._copy_xauthority_file(temp_dir) |
3654 | + self.useFixture(toolkit_fixtures.InitctlEnvironmentVariable( |
3655 | + HOME=temp_dir)) |
3656 | else: |
3657 | - patcher = mock.patch.dict('os.environ', {'HOME': temp_dir}) |
3658 | - patcher.start() |
3659 | - self.addCleanup(patcher.stop) |
3660 | - |
3661 | - logger.debug("Patched home to fake home directory " + temp_dir) |
3662 | + temp_dir_fixture = fixtures.TempDir() |
3663 | + self.useFixture(temp_dir_fixture) |
3664 | + temp_dir = temp_dir_fixture.path |
3665 | + |
3666 | + #before we set fixture, copy xauthority if needed |
3667 | + self._copy_xauthority_file(temp_dir) |
3668 | + self.useFixture(fixtures.EnvironmentVariable('HOME', |
3669 | + newvalue=temp_dir)) |
3670 | + |
3671 | + logger.debug("Patched home to fake home directory %s" % temp_dir) |
3672 | return temp_dir |
3673 | |
3674 | def _create_music_library(self): |
3675 | @@ -132,8 +264,10 @@ |
3676 | logger.debug("Home set to %s" % self.home_dir) |
3677 | musicpath = os.path.join(self.home_dir, 'Music') |
3678 | logger.debug("Music path set to %s" % musicpath) |
3679 | - mediascannerpath = os.path.join(self.home_dir, '.cache/mediascanner') |
3680 | - os.mkdir(musicpath) |
3681 | + mediascannerpath = os.path.join(self.home_dir, |
3682 | + '.cache/mediascanner-2.0') |
3683 | + if not os.path.exists(musicpath): |
3684 | + os.makedirs(musicpath) |
3685 | logger.debug("Mediascanner path set to %s" % mediascannerpath) |
3686 | |
3687 | #set content path |
3688 | @@ -147,11 +281,12 @@ |
3689 | shutil.copy(os.path.join(content_dir, '2.ogg'), musicpath) |
3690 | shutil.copy(os.path.join(content_dir, '3.mp3'), musicpath) |
3691 | shutil.copytree( |
3692 | - os.path.join(content_dir, 'mediascanner'), mediascannerpath) |
3693 | + os.path.join(content_dir, 'mediascanner-2.0'), mediascannerpath) |
3694 | |
3695 | logger.debug("Music copied, files " + str(os.listdir(musicpath))) |
3696 | |
3697 | self._patch_mediascanner_home(mediascannerpath) |
3698 | + |
3699 | logger.debug( |
3700 | "Mediascanner database copied, files " + |
3701 | str(os.listdir(mediascannerpath))) |
3702 | @@ -160,18 +295,24 @@ |
3703 | #do some inline db patching |
3704 | #patch mediaindex to proper home |
3705 | #these values are dependent upon our sampled db |
3706 | - logger.debug("Patching fake mediascanner database") |
3707 | + logger.debug("Patching fake mediascanner database in %s" % |
3708 | + mediascannerpath) |
3709 | + logger.debug( |
3710 | + "Mediascanner database files " + |
3711 | + str(os.listdir(mediascannerpath))) |
3712 | + |
3713 | relhome = self.home_dir[1:] |
3714 | - dblocation = "home/autopilot-music-app" |
3715 | - dbfoldername = "d15682c3-89f1-4e41-abfc-531e4740e5a7" |
3716 | + dblocation = "home/phablet" |
3717 | #patch mediaindex |
3718 | self._file_find_replace(mediascannerpath + |
3719 | - "/mediaindex", dblocation, relhome) |
3720 | + "/mediastore.sql", dblocation, relhome) |
3721 | |
3722 | - #patch file indexes |
3723 | - index_template = '%s/%s/_%%s.cfs' % (mediascannerpath, dbfoldername) |
3724 | - for i in range(5): |
3725 | - self._file_find_replace(index_template % i, dblocation, relhome) |
3726 | + con = sqlite3.connect(mediascannerpath + "/mediastore.db") |
3727 | + f = open(mediascannerpath + "/mediastore.sql", 'r') |
3728 | + sql = f.read() |
3729 | + cur = con.cursor() |
3730 | + cur.executescript(sql) |
3731 | + con.close() |
3732 | |
3733 | def _file_find_replace(self, in_filename, find, replace): |
3734 | #replace all occurences of string find with string replace |
3735 | @@ -188,6 +329,55 @@ |
3736 | os.remove(in_filename) |
3737 | os.rename(out_filename, in_filename) |
3738 | |
3739 | + def backup_folder(self, folder): |
3740 | + backup_dir = os.path.join(self.backup_root, os.path.basename(folder)) |
3741 | + logger.debug('Backup dir set to %s' % backup_dir) |
3742 | + try: |
3743 | + shutil.rmtree(backup_dir) |
3744 | + except: |
3745 | + pass |
3746 | + else: |
3747 | + logger.warning("Prexisting backup found and removed") |
3748 | + |
3749 | + try: |
3750 | + shutil.move(folder, backup_dir) |
3751 | + except shutil.Error as e: |
3752 | + logger.error('Backup error for %s: %s' % (folder, e)) |
3753 | + except IOError as e: |
3754 | + logger.error('Backup error for %s: %s' % (folder, e.strerror)) |
3755 | + except: |
3756 | + logger.error("Unknown error backing up %s" % folder) |
3757 | + else: |
3758 | + logger.debug('Backed up %s to %s' % (folder, backup_dir)) |
3759 | + |
3760 | + def restore_folder(self, folder): |
3761 | + backup_dir = os.path.join(self.backup_root, os.path.basename(folder)) |
3762 | + logger.debug('Backup dir set to %s' % backup_dir) |
3763 | + if os.path.exists(backup_dir): |
3764 | + if os.path.exists(folder): |
3765 | + try: |
3766 | + shutil.rmtree(folder) |
3767 | + except shutil.Error as e: |
3768 | + logger.error('Restore error for %s: %s' % (folder, e)) |
3769 | + except IOError as e: |
3770 | + logger.error('Restore error for %s: %s' % |
3771 | + (folder, e.strerror)) |
3772 | + except: |
3773 | + logger.error("Failed to remove test data for %s" % folder) |
3774 | + return |
3775 | + try: |
3776 | + shutil.move(backup_dir, folder) |
3777 | + except shutil.Error as e: |
3778 | + logger.error('Restore error for %s: %s' % (folder, e)) |
3779 | + except IOError as e: |
3780 | + logger.error('Restore error for %s: %s' % (folder, e.strerror)) |
3781 | + except: |
3782 | + logger.error('Unknown error restoring %s' % folder) |
3783 | + else: |
3784 | + logger.debug('Restored %s from %s' % (folder, backup_dir)) |
3785 | + else: |
3786 | + logger.warn('No backup found to restore for %s' % folder) |
3787 | + |
3788 | @property |
3789 | def player(self): |
3790 | return self.main_view.get_player() |
3791 | |
3792 | === modified file 'tests/autopilot/music_app/tests/test_music.py' |
3793 | --- tests/autopilot/music_app/tests/test_music.py 2014-05-21 07:23:35 +0000 |
3794 | +++ tests/autopilot/music_app/tests/test_music.py 2014-06-19 01:49:30 +0000 |
3795 | @@ -1,5 +1,5 @@ |
3796 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3797 | -# Copyright 2013 Canonical |
3798 | +# Copyright 2013, 2014 Canonical |
3799 | # |
3800 | # This program is free software: you can redistribute it and/or modify it |
3801 | # under the terms of the GNU General Public License version 3, as published |
3802 | @@ -21,25 +21,35 @@ |
3803 | |
3804 | |
3805 | class TestMainWindow(MusicTestCase): |
3806 | - FIRST_TITLE = "Foss Yeaaaah! (Radio Edit)" |
3807 | - LAST_TITLE = "TestMP3Title" |
3808 | |
3809 | def setUp(self): |
3810 | super(TestMainWindow, self).setUp() |
3811 | self.assertThat( |
3812 | self.main_view.visible, Eventually(Equals(True))) |
3813 | + |
3814 | #wait for activity indicator to stop spinning |
3815 | spinner = lambda: self.main_view.get_spinner().running |
3816 | self.assertThat(spinner, Eventually(Equals(False))) |
3817 | + self.trackTitle = u"Gran Vals" |
3818 | + self.artistName = u"Francisco Tárrega" |
3819 | + self.lastTrackTitle = u"TestMP3Title" |
3820 | |
3821 | def populate_and_play_queue(self): |
3822 | first_genre_item = self.main_view.get_first_genre_item() |
3823 | self.pointing_device.click_object(first_genre_item) |
3824 | |
3825 | - title = self.FIRST_TITLE |
3826 | - song = self.main_view.get_album_sheet_listview_tracktitle(title) |
3827 | + song = self.main_view.get_album_sheet_listview_tracktitle( |
3828 | + self.trackTitle) |
3829 | self.pointing_device.click_object(song) |
3830 | |
3831 | + def populate_and_play_queue_from_songs_tab(self): |
3832 | + # switch to songs tab |
3833 | + self.main_view.switch_to_tab("trackstab") |
3834 | + |
3835 | + # get track item to add to queue |
3836 | + trackitem = self.main_view.get_songs_tab_tracktitle(self.trackTitle) |
3837 | + self.pointing_device.click_object(trackitem) |
3838 | + |
3839 | def turn_shuffle_off(self): |
3840 | if self.player.shuffle: |
3841 | shufflebutton = self.main_view.get_shuffle_button() |
3842 | @@ -81,55 +91,63 @@ |
3843 | fake mediascanner database""" |
3844 | |
3845 | # populate queue |
3846 | - first_genre_item = self.main_view.get_first_genre_item() |
3847 | - self.pointing_device.click_object(first_genre_item) |
3848 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3849 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
3850 | - self.pointing_device.click_object(song) |
3851 | + self.populate_and_play_queue_from_songs_tab() |
3852 | |
3853 | title = lambda: self.player.currentMetaTitle |
3854 | artist = lambda: self.player.currentMetaArtist |
3855 | - self.assertThat(title, |
3856 | - Eventually(Equals("Foss Yeaaaah! (Radio Edit)"))) |
3857 | - self.assertThat(artist, Eventually(Equals("Benjamin Kerensa"))) |
3858 | + self.assertThat(title, Eventually(Equals(self.trackTitle))) |
3859 | + self.assertThat(artist, Eventually(Equals(self.artistName))) |
3860 | |
3861 | def test_play_pause_library(self): |
3862 | """ Test playing and pausing a track (Music Library must exist) """ |
3863 | |
3864 | - # populate queue |
3865 | - first_genre_item = self.main_view.get_first_genre_item() |
3866 | - self.pointing_device.click_object(first_genre_item) |
3867 | - button = self.main_view.get_add_to_queue_button() |
3868 | - self.pointing_device.click_object(button) |
3869 | - |
3870 | - # click on close button to close genre sheet |
3871 | + # get number of tracks in queue before queuing a track |
3872 | + initialtracksCount = self.main_view.get_queue_track_count() |
3873 | + |
3874 | + self.main_view.add_to_queue_from_albums_tab_album_sheet( |
3875 | + self.artistName, self.trackTitle) |
3876 | + |
3877 | + # verify track queue has added one to initial value |
3878 | + endtracksCount = self.main_view.get_queue_track_count() |
3879 | + self.assertThat(endtracksCount, Equals(initialtracksCount + 1)) |
3880 | + |
3881 | + #Assert that the song added to the list is not playing |
3882 | + self.assertThat(self.player.currentIndex, |
3883 | + Eventually(NotEquals(endtracksCount))) |
3884 | + self.assertThat(self.player.isPlaying, Eventually(Equals(False))) |
3885 | + |
3886 | + #verify song's metadata matches the item added to the Now Playing view |
3887 | + queueArtistName = self.main_view.get_queue_now_playing_artist( |
3888 | + self.artistName) |
3889 | + self.assertThat(queueArtistName.text, Equals(self.artistName)) |
3890 | + queueTrackTitle = self.main_view.get_queue_now_playing_title( |
3891 | + self.trackTitle) |
3892 | + self.assertThat(queueTrackTitle.text, Equals(self.trackTitle)) |
3893 | + |
3894 | + # click on close button to close album sheet |
3895 | closebutton = self.main_view.get_album_sheet_close_button() |
3896 | self.pointing_device.click_object(closebutton) |
3897 | + self.assertThat(self.main_view.get_albumstab(), Not(Is(None))) |
3898 | |
3899 | if self.main_view.wideAspect: |
3900 | - playbutton = self.main_view.get_now_playing_play_button() |
3901 | + play_button = self.main_view.get_now_playing_play_button() |
3902 | else: |
3903 | - playbutton = self.main_view.get_play_button() |
3904 | - |
3905 | - self.main_view.show_toolbar() |
3906 | + play_button = self.main_view.get_play_button() |
3907 | + self.main_view.show_toolbar() |
3908 | |
3909 | """ Track is playing""" |
3910 | - self.pointing_device.click_object(playbutton) |
3911 | + self.pointing_device.click_object(play_button) |
3912 | self.assertThat(self.player.isPlaying, Eventually(Equals(True))) |
3913 | |
3914 | """ Track is not playing""" |
3915 | - self.pointing_device.click_object(playbutton) |
3916 | + self.pointing_device.click_object(play_button) |
3917 | self.assertThat(self.player.isPlaying, Eventually(Equals(False))) |
3918 | |
3919 | def test_play_pause_now_playing(self): |
3920 | """ Test playing and pausing a track (Music Library must exist) """ |
3921 | |
3922 | # populate queue |
3923 | - first_genre_item = self.main_view.get_first_genre_item() |
3924 | - self.pointing_device.click_object(first_genre_item) |
3925 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3926 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
3927 | - self.pointing_device.click_object(song) |
3928 | + self.populate_and_play_queue_from_songs_tab() |
3929 | |
3930 | playbutton = self.main_view.get_now_playing_play_button() |
3931 | |
3932 | @@ -148,11 +166,7 @@ |
3933 | """ Test going to next track (Music Library must exist) """ |
3934 | |
3935 | # populate queue |
3936 | - first_genre_item = self.main_view.get_first_genre_item() |
3937 | - self.pointing_device.click_object(first_genre_item) |
3938 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3939 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
3940 | - self.pointing_device.click_object(song) |
3941 | + self.populate_and_play_queue_from_songs_tab() |
3942 | |
3943 | playbutton = self.main_view.get_now_playing_play_button() |
3944 | |
3945 | @@ -206,11 +220,7 @@ |
3946 | """ Test that mp3 "plays" or at least doesn't crash on load """ |
3947 | |
3948 | # populate queue |
3949 | - first_genre_item = self.main_view.get_first_genre_item() |
3950 | - self.pointing_device.click_object(first_genre_item) |
3951 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3952 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
3953 | - self.pointing_device.click_object(song) |
3954 | + self.populate_and_play_queue_from_songs_tab() |
3955 | |
3956 | playbutton = self.main_view.get_now_playing_play_button() |
3957 | |
3958 | @@ -253,11 +263,7 @@ |
3959 | """ Test shuffle (Music Library must exist) """ |
3960 | |
3961 | # populate queue |
3962 | - first_genre_item = self.main_view.get_first_genre_item() |
3963 | - self.pointing_device.click_object(first_genre_item) |
3964 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3965 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
3966 | - self.pointing_device.click_object(song) |
3967 | + self.populate_and_play_queue_from_songs_tab() |
3968 | |
3969 | """ Track is playing, shuffle is turned on""" |
3970 | forwardbutton = self.main_view.get_forward_button() |
3971 | @@ -326,18 +332,16 @@ |
3972 | def test_show_albums_sheet(self): |
3973 | """tests navigating to the Albums tab and displaying the album sheet""" |
3974 | |
3975 | - artistName = "Benjamin Kerensa" |
3976 | - |
3977 | # switch to albums tab |
3978 | self.main_view.switch_to_tab("albumstab") |
3979 | |
3980 | #select album |
3981 | - albumartist = self.main_view.get_albums_albumartist(artistName) |
3982 | + albumartist = self.main_view.get_albums_albumartist(self.artistName) |
3983 | self.pointing_device.click_object(albumartist) |
3984 | |
3985 | #get album sheet album artist |
3986 | sheet_albumartist = self.main_view.get_album_sheet_artist() |
3987 | - self.assertThat(sheet_albumartist.text, Equals(artistName)) |
3988 | + self.assertThat(sheet_albumartist.text, Equals(self.artistName)) |
3989 | |
3990 | # click on close button to close album sheet |
3991 | closebutton = self.main_view.get_album_sheet_close_button() |
3992 | @@ -347,31 +351,11 @@ |
3993 | def test_add_song_to_queue_from_albums_sheet(self): |
3994 | """tests navigating to the Albums tab and adding a song to queue""" |
3995 | |
3996 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
3997 | - artistName = "Benjamin Kerensa" |
3998 | - |
3999 | # get number of tracks in queue before queuing a track |
4000 | initialtracksCount = self.main_view.get_queue_track_count() |
4001 | |
4002 | - # switch to albums tab |
4003 | - self.main_view.switch_to_tab("albumstab") |
4004 | - |
4005 | - #select album |
4006 | - albumartist = self.main_view.get_albums_albumartist(artistName) |
4007 | - self.pointing_device.click_object(albumartist) |
4008 | - |
4009 | - #get album sheet album artist |
4010 | - sheet_albumartist = self.main_view.get_album_sheet_artist() |
4011 | - self.assertThat(sheet_albumartist.text, Equals(artistName)) |
4012 | - |
4013 | - #get track item to add to queue |
4014 | - trackicon = self.main_view.get_album_sheet_listview_trackicon( |
4015 | - trackTitle) |
4016 | - self.pointing_device.click_object(trackicon) |
4017 | - |
4018 | - #click on Add to queue |
4019 | - queueTrackLabel = self.main_view.get_album_sheet_queuetrack_label() |
4020 | - self.pointing_device.click_object(queueTrackLabel) |
4021 | + self.main_view.add_to_queue_from_albums_tab_album_sheet( |
4022 | + self.artistName, self.trackTitle) |
4023 | |
4024 | # verify track queue has added one to initial value |
4025 | endtracksCount = self.main_view.get_queue_track_count() |
4026 | @@ -384,11 +368,11 @@ |
4027 | |
4028 | #verify song's metadata matches the item added to the Now Playing view |
4029 | queueArtistName = self.main_view.get_queue_now_playing_artist( |
4030 | - artistName) |
4031 | - self.assertThat(str(queueArtistName.text), Equals(artistName)) |
4032 | + self.artistName) |
4033 | + self.assertThat(queueArtistName.text, Equals(self.artistName)) |
4034 | queueTrackTitle = self.main_view.get_queue_now_playing_title( |
4035 | - trackTitle) |
4036 | - self.assertThat(str(queueTrackTitle.text), Equals(trackTitle)) |
4037 | + self.trackTitle) |
4038 | + self.assertThat(queueTrackTitle.text, Equals(self.trackTitle)) |
4039 | |
4040 | # click on close button to close album sheet |
4041 | closebutton = self.main_view.get_album_sheet_close_button() |
4042 | @@ -399,18 +383,11 @@ |
4043 | """tests navigating to the Songs tab and adding the library to the |
4044 | queue with the selected item being played. """ |
4045 | |
4046 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
4047 | - artistName = "Benjamin Kerensa" |
4048 | - |
4049 | # get number of tracks in queue before queuing a track |
4050 | initialtracksCount = self.main_view.get_queue_track_count() |
4051 | |
4052 | - # switch to songs tab |
4053 | - self.main_view.switch_to_tab("trackstab") |
4054 | - |
4055 | - # get track item to add to queue |
4056 | - trackitem = self.main_view.get_songs_tab_tracktitle(trackTitle) |
4057 | - self.pointing_device.click_object(trackitem) |
4058 | + # populate queue |
4059 | + self.populate_and_play_queue_from_songs_tab() |
4060 | |
4061 | # verify track queue has added all songs to initial value |
4062 | endtracksCount = self.main_view.get_queue_track_count() |
4063 | @@ -423,19 +400,16 @@ |
4064 | |
4065 | # verify song's metadata matches the item added to the Now Playing view |
4066 | queueArtistName = self.main_view.get_queue_now_playing_artist( |
4067 | - artistName) |
4068 | - self.assertThat(str(queueArtistName.text), Equals(artistName)) |
4069 | + self.artistName) |
4070 | + self.assertThat(queueArtistName.text, Equals(self.artistName)) |
4071 | queueTrackTitle = self.main_view.get_queue_now_playing_title( |
4072 | - trackTitle) |
4073 | - self.assertThat(str(queueTrackTitle.text), Equals(trackTitle)) |
4074 | + self.trackTitle) |
4075 | + self.assertThat(queueTrackTitle.text, Equals(self.trackTitle)) |
4076 | |
4077 | def test_add_song_to_queue_from_songs_tab(self): |
4078 | """tests navigating to the Songs tab and adding a song from the library |
4079 | to the queue via the expandable list view item. """ |
4080 | |
4081 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
4082 | - artistName = "Benjamin Kerensa" |
4083 | - |
4084 | # get number of tracks in queue before queuing a track |
4085 | initialtracksCount = self.main_view.get_queue_track_count() |
4086 | |
4087 | @@ -443,7 +417,7 @@ |
4088 | self.main_view.switch_to_tab("trackstab") |
4089 | |
4090 | # get track item to add to queue |
4091 | - trackitem = self.main_view.get_songs_tab_trackimage(trackTitle) |
4092 | + trackitem = self.main_view.get_songs_tab_trackimage(self.trackTitle) |
4093 | self.pointing_device.click_object(trackitem) |
4094 | addtoqueueLabel = self.main_view.get_songs_tab_add_to_queue_label() |
4095 | self.pointing_device.click_object(addtoqueueLabel) |
4096 | @@ -459,23 +433,21 @@ |
4097 | |
4098 | # verify song's metadata matches the item added to the Now Playing view |
4099 | queueArtistName = self.main_view.get_queue_now_playing_artist( |
4100 | - artistName) |
4101 | - self.assertThat(str(queueArtistName.text), Equals(artistName)) |
4102 | + self.artistName) |
4103 | + self.assertThat(queueArtistName.text, Equals(self.artistName)) |
4104 | queueTrackTitle = self.main_view.get_queue_now_playing_title( |
4105 | - trackTitle) |
4106 | - self.assertThat(str(queueTrackTitle.text), Equals(trackTitle)) |
4107 | + self.trackTitle) |
4108 | + self.assertThat(queueTrackTitle.text, Equals(self.trackTitle)) |
4109 | |
4110 | def test_create_playlist_from_songs_tab(self): |
4111 | """tests navigating to the Songs tab and creating a playlist by |
4112 | selecting a song to add it to a new playlist. """ |
4113 | |
4114 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
4115 | - |
4116 | # switch to songs tab |
4117 | self.main_view.switch_to_tab("trackstab") |
4118 | |
4119 | # get track item to add to queue |
4120 | - trackitem = self.main_view.get_songs_tab_trackimage(trackTitle) |
4121 | + trackitem = self.main_view.get_songs_tab_trackimage(self.trackTitle) |
4122 | self.pointing_device.click_object(trackitem) |
4123 | addtoplaylistLbl = self.main_view.get_songs_tab_add_to_playlist_label() |
4124 | self.pointing_device.click_object(addtoplaylistLbl) |
4125 | @@ -513,9 +485,6 @@ |
4126 | def test_artists_tab_album(self): |
4127 | """tests navigating to the Artists tab and playing an album""" |
4128 | |
4129 | - artistName = "Benjamin Kerensa" |
4130 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
4131 | - |
4132 | # get number of tracks in queue before queuing a track |
4133 | initialtracksCount = self.main_view.get_queue_track_count() |
4134 | |
4135 | @@ -523,12 +492,12 @@ |
4136 | self.main_view.switch_to_tab("artiststab") |
4137 | |
4138 | #select artist |
4139 | - artist = self.main_view.get_artists_artist(artistName) |
4140 | + artist = self.main_view.get_artists_artist(self.artistName) |
4141 | self.pointing_device.click_object(artist) |
4142 | |
4143 | #get album sheet album artist |
4144 | sheet_albumartist = self.main_view.get_artist_sheet_artist() |
4145 | - self.assertThat(sheet_albumartist.text, Equals(artistName)) |
4146 | + self.assertThat(sheet_albumartist.text, Equals(self.artistName)) |
4147 | |
4148 | # click on album to shows the artists |
4149 | sheet_albumartist = self.main_view.get_artist_sheet_artist_cover() |
4150 | @@ -536,13 +505,14 @@ |
4151 | |
4152 | #get song sheet album artist |
4153 | sheet_albumartist = self.main_view.get_album_sheet_artist() |
4154 | - self.assertThat(sheet_albumartist.text, Equals(artistName)) |
4155 | + self.assertThat(sheet_albumartist.text, Equals(self.artistName)) |
4156 | |
4157 | # click on song to populate queue and start playing |
4158 | self.pointing_device.click_object(sheet_albumartist) |
4159 | |
4160 | #select artist |
4161 | - track = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
4162 | + track = self.main_view.get_album_sheet_listview_tracktitle( |
4163 | + self.trackTitle) |
4164 | self.pointing_device.click_object(track) |
4165 | |
4166 | # verify track queue has added all songs to initial value |
4167 | @@ -556,31 +526,25 @@ |
4168 | |
4169 | # verify song's metadata matches the item added to the Now Playing view |
4170 | queueArtistName = self.main_view.get_queue_now_playing_artist( |
4171 | - artistName) |
4172 | - self.assertThat(str(queueArtistName.text), Equals(artistName)) |
4173 | + self.artistName) |
4174 | + self.assertThat(queueArtistName.text, Equals(self.artistName)) |
4175 | queueTrackTitle = self.main_view.get_queue_now_playing_title( |
4176 | - trackTitle) |
4177 | - self.assertThat(str(queueTrackTitle.text), Equals(trackTitle)) |
4178 | + self.trackTitle) |
4179 | + self.assertThat(queueTrackTitle.text, Equals(self.trackTitle)) |
4180 | |
4181 | def test_swipe_to_delete_song(self): |
4182 | """tests navigating to the Now Playing queue, swiping to delete a |
4183 | track, and confirming the delete action. """ |
4184 | |
4185 | - artistName = "Benjamin Kerensa" |
4186 | - |
4187 | # populate queue |
4188 | - first_genre_item = self.main_view.get_first_genre_item() |
4189 | - self.pointing_device.click_object(first_genre_item) |
4190 | - trackTitle = "Foss Yeaaaah! (Radio Edit)" |
4191 | - song = self.main_view.get_album_sheet_listview_tracktitle(trackTitle) |
4192 | - self.pointing_device.click_object(song) |
4193 | + self.populate_and_play_queue_from_songs_tab() |
4194 | |
4195 | # get initial queue count |
4196 | initialqueueCount = self.main_view.get_queue_track_count() |
4197 | |
4198 | # get song to delete |
4199 | artistToDelete = self.main_view.get_queue_now_playing_artist( |
4200 | - artistName) |
4201 | + self.artistName) |
4202 | musicnowplayingpage = self.main_view.get_MusicNowPlaying_page() |
4203 | |
4204 | # get coordinates to delete song |
4205 | @@ -604,7 +568,10 @@ |
4206 | |
4207 | def test_playback_stops_when_last_song_ends_and_repeat_off(self): |
4208 | """Check that playback stops when the last song in the queue ends""" |
4209 | - self.populate_and_play_queue() |
4210 | + |
4211 | + # populate queue |
4212 | + self.populate_and_play_queue_from_songs_tab() |
4213 | + |
4214 | self.turn_shuffle_off() |
4215 | self.turn_repeat_off() |
4216 | |
4217 | @@ -620,7 +587,10 @@ |
4218 | |
4219 | def test_playback_repeats_when_last_song_ends_and_repeat_on(self): |
4220 | """With repeat on, the 1st song should play after the last one ends""" |
4221 | - self.populate_and_play_queue() |
4222 | + |
4223 | + # populate queue |
4224 | + self.populate_and_play_queue_from_songs_tab() |
4225 | + |
4226 | self.turn_shuffle_off() |
4227 | self.turn_repeat_on() |
4228 | |
4229 | @@ -632,12 +602,15 @@ |
4230 | |
4231 | #Make sure we loop back to first song after last song ends |
4232 | actual_title = lambda: self.player.currentMetaTitle |
4233 | - self.assertThat(actual_title, Eventually(Equals(self.FIRST_TITLE))) |
4234 | + self.assertThat(actual_title, Eventually(Equals(self.trackTitle))) |
4235 | self.assertThat(self.player.isPlaying, Eventually(Equals(True))) |
4236 | |
4237 | def test_pressing_next_from_last_song_plays_first_when_repeat_on(self): |
4238 | """With repeat on, skipping the last song jumps to the first track""" |
4239 | - self.populate_and_play_queue() |
4240 | + |
4241 | + # populate queue |
4242 | + self.populate_and_play_queue_from_songs_tab() |
4243 | + |
4244 | self.turn_shuffle_off() |
4245 | self.turn_repeat_on() |
4246 | |
4247 | @@ -648,12 +621,15 @@ |
4248 | self.pointing_device.click_object(forward_button) |
4249 | |
4250 | actual_title = lambda: self.player.currentMetaTitle |
4251 | - self.assertThat(actual_title, Eventually(Equals(self.FIRST_TITLE))) |
4252 | + self.assertThat(actual_title, Eventually(Equals(self.trackTitle))) |
4253 | self.assertThat(self.player.isPlaying, Eventually(Equals(True))) |
4254 | |
4255 | def test_pressing_prev_from_first_song_plays_last_when_repeat_on(self): |
4256 | """With repeat on, 'previous' from the 1st song plays the last one.""" |
4257 | - self.populate_and_play_queue() |
4258 | + |
4259 | + # populate queue |
4260 | + self.populate_and_play_queue_from_songs_tab() |
4261 | + |
4262 | self.turn_shuffle_off() |
4263 | self.turn_repeat_on() |
4264 | |
4265 | @@ -667,5 +643,5 @@ |
4266 | self.pointing_device.click_object(prev_button) |
4267 | |
4268 | actual_title = lambda: self.player.currentMetaTitle |
4269 | - self.assertThat(actual_title, Eventually(Equals(self.LAST_TITLE))) |
4270 | + self.assertThat(actual_title, Eventually(Equals(self.lastTrackTitle))) |
4271 | self.assertThat(self.player.isPlaying, Eventually(Equals(True))) |
4272 | |
4273 | === modified file 'worker-library-loader.js' |
4274 | --- worker-library-loader.js 2013-12-05 00:23:08 +0000 |
4275 | +++ worker-library-loader.js 2014-06-19 01:49:30 +0000 |
4276 | @@ -1,7 +1,8 @@ |
4277 | /* |
4278 | - * Copyright (C) 2013 Andrew Hayzen <ahayzen@gmail.com> |
4279 | - * Daniel Holm <d.holmen@gmail.com> |
4280 | - * Victor Thompson <victor.thompson@gmail.com> |
4281 | + * Copyright (C) 2013, 2014 |
4282 | + * Andrew Hayzen <ahayzen@gmail.com> |
4283 | + * Daniel Holm <d.holmen@gmail.com> |
4284 | + * Victor Thompson <victor.thompson@gmail.com> |
4285 | * |
4286 | * This program is free software; you can redistribute it and/or modify |
4287 | * it under the terms of the GNU General Public License as published by |
Commenting here so I don't lose this. Once the plugin is gone, we can make use of the on device testing for mp's (because we'll have a proper click package that includes all the plugins)