Merge lp:~music-app-dev/music-app/frankenstein-merge into lp:music-app/trusty
- frankenstein-merge
- Merge into trusty
Status: | Merged |
---|---|
Approved by: | Victor Thompson |
Approved revision: | 33 |
Merged at revision: | 24 |
Proposed branch: | lp:~music-app-dev/music-app/frankenstein-merge |
Merge into: | lp:music-app/trusty |
Diff against target: |
1700 lines (+780/-705) 9 files modified
FirstRun.qml (+0/-54) MusicSettings.qml (+13/-7) MusicTracks.qml (+627/-96) QueueDialog.qml (+4/-4) Toolbar.qml (+0/-103) debian/changelog (+7/-1) debian/install (+9/-1) music-app.qml (+86/-439) playing-list.js (+34/-0) |
To merge this branch: | bzr merge lp:~music-app-dev/music-app/frankenstein-merge |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Martin Mrazik (community) | Approve | ||
Daniel Holm | Approve | ||
Review via email:
|
Commit message
Merged my existing lp:ubuntu-music-app code into the trunk.
* Replaced current UI
* Replaced playback functionality and managment
* Added some UI (that wasn't in my upstream) so we can do context switching from a tracks view to a playlist view or artists/albums.
* Fixed shuffling behavoir and retrieving/setting of the shuffle parameter setting
* Currently the Queue will add items on "press and hold", but the tracks are not playable. As we move forward, the Queue should just be another ListView. The same will go for playlists.
Description of the change
Merged my existing lp:ubuntu-music-app code into the trunk.
* Replaced current UI
* Replaced playback functionality and managment
* Added some UI (that wasn't in my upstream) so we can do context switching from a tracks view to a playlist view or artists/albums.
* Fixed shuffling behavoir and retrieving/setting of the shuffle parameter setting
* Currently the Queue will add items on "press and hold", but the tracks are not playable. As we move forward, the Queue should just be another ListView. The same will go for playlists.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:28
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Daniel Holm (danielholm) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Daniel Holm (danielholm) wrote : | # |
I think I've fixed the error. Trying again.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:29
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:31
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
Unapproved changes made after approval.
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:32
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Martin Mrazik (mrazik) wrote : | # |
Mhm... This fails to land in a weird way but it looks like the changelog is badly formatted:
----snip----
bzrlib.
-------
AFAICS there is a missing space after e-mail address:
-- maintainer name <email address>[two spaces] date
It is weird the CI build passes but apparently that check is missing there.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Thompson (vthompson) wrote : | # |
Issue has been fixed. Maybe someone needs to put Jenkins in "needs review"
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Martin Mrazik (mrazik) wrote : | # |
Feel free to approve. Jenkins should pick it up now. Sorry for the hassle.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:33
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:33
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === removed file 'FirstRun.qml' |
2 | --- FirstRun.qml 2013-05-31 13:58:43 +0000 |
3 | +++ FirstRun.qml 1970-01-01 00:00:00 +0000 |
4 | @@ -1,54 +0,0 @@ |
5 | -/* |
6 | - * Copyleft Daniel Holm. |
7 | - * |
8 | - * Authors: |
9 | - * Daniel Holm <d.holmen@gmail.com> |
10 | - * |
11 | - * This program is free software; you can redistribute it and/or modify |
12 | - * it under the terms of the GNU General Public License as published by |
13 | - * the Free Software Foundation; version 3. |
14 | - * |
15 | - * This program is distributed in the hope that it will be useful, |
16 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | - * GNU General Public License for more details. |
19 | - * |
20 | - * You should have received a copy of the GNU General Public License |
21 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | - */ |
23 | - |
24 | -import QtQuick 2.0 |
25 | -import Ubuntu.Components 0.1 |
26 | -import Ubuntu.Components.ListItems 0.1 as ListItem |
27 | -import Ubuntu.Components.Popups 0.1 |
28 | -import QtQuick.LocalStorage 2.0 |
29 | -import "settings.js" as Settings |
30 | - |
31 | -Dialog { |
32 | - id: root |
33 | - title: i18n.tr("First Run") |
34 | - text: i18n.tr("This appears to be your first run. Please set your music directory.") |
35 | - |
36 | - Row { |
37 | - spacing: units.gu(2) |
38 | - TextField { |
39 | - id: musicDirField |
40 | - placeholderText: "/home/username/Music" |
41 | - hasClearButton: false |
42 | - text: musicDir |
43 | - } |
44 | - } |
45 | - |
46 | - Button { |
47 | - text: i18n.tr("Save") |
48 | - color: "green" |
49 | - onClicked: { |
50 | - PopupUtils.close(root) |
51 | - // set new music dir |
52 | - Settings.initialize() |
53 | - Settings.setSetting("currentfolder", musicDirField.text) |
54 | - console.debug("Debug: Set new music dir to: "+musicDirField.text) |
55 | - } |
56 | - } |
57 | - |
58 | -} |
59 | |
60 | === modified file 'MusicSettings.qml' |
61 | --- MusicSettings.qml 2013-05-31 14:58:23 +0000 |
62 | +++ MusicSettings.qml 2013-06-05 04:48:28 +0000 |
63 | @@ -3,6 +3,7 @@ |
64 | * |
65 | * Authors: |
66 | * Daniel Holm <d.holmen@gmail.com> |
67 | + * Victor Thompson <victor.thompson@gmail.com> |
68 | * |
69 | * This program is free software; you can redistribute it and/or modify |
70 | * it under the terms of the GNU General Public License as published by |
71 | @@ -31,9 +32,13 @@ |
72 | spacing: units.gu(2) |
73 | TextField { |
74 | id: musicDirField |
75 | - placeholderText: "/home/username/Music" |
76 | + placeholderText: folderModel.homePath() + "/Music" |
77 | hasClearButton: false |
78 | - text: musicDir |
79 | + text: Settings.getSetting("currentfolder") |
80 | + |
81 | + onTextChanged: { |
82 | + Settings.setSetting("currentfolder", text) |
83 | + } |
84 | } |
85 | } |
86 | |
87 | @@ -45,8 +50,8 @@ |
88 | width: units.gu(20) |
89 | } |
90 | Switch { |
91 | - id: scrobbleSwitch |
92 | - checked: shuffleState |
93 | + id: shuffleSwitch |
94 | + checked: Settings.getSetting("shuffle") === "1" |
95 | } |
96 | } |
97 | |
98 | @@ -97,7 +102,7 @@ |
99 | Row { |
100 | ListItem.Subtitled { |
101 | text: "Music "+appVersion |
102 | - subText: i18n.tr("By Daniel Holm, Sweden") |
103 | + subText: i18n.tr("By Daniel Holm (Sweden) and\nVictor Thompson (USA)") |
104 | } |
105 | } |
106 | |
107 | @@ -142,9 +147,10 @@ |
108 | // set new music dir |
109 | Settings.initialize() |
110 | Settings.setSetting("currentfolder", musicDirField.text) // save music dir |
111 | - Settings.setSetting("shuffle", scrobbleSwitch.checked) // save shuffle state |
112 | + Settings.setSetting("shuffle", shuffleSwitch.checked) // save shuffle state |
113 | + random = shuffleSwitch.checked |
114 | console.debug("Debug: Set new music dir to: "+musicDirField.text) |
115 | - console.debug("Debug: Shuffle: "+scrobbleSwitch.checked) |
116 | + console.debug("Debug: Shuffle: "+ shuffleSwitch.checked) |
117 | } |
118 | } |
119 | |
120 | |
121 | === modified file 'MusicTracks.qml' |
122 | --- MusicTracks.qml 2013-05-31 14:58:23 +0000 |
123 | +++ MusicTracks.qml 2013-06-05 04:48:28 +0000 |
124 | @@ -3,6 +3,7 @@ |
125 | * |
126 | * Authors: |
127 | * Daniel Holm <d.holmen@gmail.com> |
128 | + * Victor Thompson <victor.thompson@gmail.com> |
129 | * |
130 | * This program is free software; you can redistribute it and/or modify |
131 | * it under the terms of the GNU General Public License as published by |
132 | @@ -22,119 +23,649 @@ |
133 | import Ubuntu.Components.ListItems 0.1 |
134 | import Ubuntu.Components.Popups 0.1 |
135 | import Ubuntu.Components.ListItems 0.1 as ListItem |
136 | -import Qt.labs.folderlistmodel 1.0 |
137 | +import org.nemomobile.folderlistmodel 1.0 |
138 | import QtMultimedia 5.0 |
139 | import QtQuick.LocalStorage 2.0 |
140 | import "settings.js" as Settings |
141 | -import "meta-database.js" as MetaDB |
142 | +import "meta-database.js" as Library |
143 | +import "playing-list.js" as PlayingList |
144 | + |
145 | |
146 | |
147 | PageStack { |
148 | - id: singleTracksPageStack |
149 | + id: pageStack |
150 | anchors.fill: parent |
151 | |
152 | + property bool needsUpdate: false |
153 | + property int filelistCurrentIndex: 0 |
154 | + property int filelistCount: 0 |
155 | + |
156 | + onFilelistCurrentIndexChanged: { |
157 | + filelist.currentIndex = filelistCurrentIndex |
158 | + } |
159 | + |
160 | + onNeedsUpdateChanged: { |
161 | + if (needsUpdate === true) { |
162 | + needsUpdate = false |
163 | + fileDurationProgressBackground.visible = true |
164 | + fileDurationProgressBackground_nowplaying.visible = true |
165 | + fileDurationProgress.width = units.gu(Math.floor((player.position*100)/player.duration) * .2) // 20 max |
166 | + fileDurationProgress_nowplaying.width = units.gu(Math.floor((player.position*100)/player.duration) * .4) // 40 max |
167 | + fileDurationBottom.text = Math.floor((player.position/1000) / 60).toString() + ":" + ( |
168 | + Math.floor((player.position/1000) % 60)<10 ? "0"+Math.floor((player.position/1000) % 60).toString() : |
169 | + Math.floor((player.position/1000) % 60).toString()) |
170 | + fileDurationBottom.text += " / " |
171 | + fileDurationBottom.text += Math.floor((player.duration/1000) / 60).toString() + ":" + ( |
172 | + Math.floor((player.duration/1000) % 60)<10 ? "0"+Math.floor((player.duration/1000) % 60).toString() : |
173 | + Math.floor((player.duration/1000) % 60).toString()) |
174 | + fileDurationBottom_nowplaying.text = fileDurationBottom.text |
175 | + } |
176 | + } |
177 | + |
178 | Component.onCompleted: { |
179 | - // initialize settings db |
180 | + pageStack.push(mainpage) |
181 | Settings.initialize() |
182 | - console.debug("INITIALIZED Settings") |
183 | - |
184 | - // If there were no database |
185 | + console.debug("INITIALIZED") |
186 | if (Settings.getSetting("initialized") !== "true") { |
187 | // initialize settings |
188 | console.debug("reset settings") |
189 | - Settings.setSetting("initialized", "true") // set that settings exists |
190 | - Settings.setSetting("shuffle", "false") // set to not shuffle as default |
191 | - Settings.setSetting("scrobble", "false") // no scrobble yet |
192 | - Settings.setSetting("currentfolder", "/") // Music dir |
193 | - // show dialog so that user can set the music dir manually, untill later |
194 | - PopupUtils.open(Qt.resolvedUrl("FirstRun.qml"), pageLayout, |
195 | - { |
196 | - title: i18n.tr("First Run") |
197 | - } ) |
198 | - } |
199 | - |
200 | - // Run as usual |
201 | - else { |
202 | - musicDir = Settings.getSetting("currentfolder") |
203 | - shuffleState = Settings.getSetting("shuffle") |
204 | - console.debug("Debug: Music dir set to: "+musicDir) |
205 | - console.debug("Debug: Shuffle state is: "+shuffleState) |
206 | - //console.debug("Debug: Scrobble state is: "+scrobbleState) |
207 | - } |
208 | - |
209 | - // then go on to meta data db |
210 | - MetaDB.initialize() // also create the metaDB |
211 | - console.debug("INITIALIZED Meta data") |
212 | - /* |
213 | - if (Settings.getSetting("initialized") !== "true") { |
214 | - // start adding tracks to db |
215 | - title = getTrackInfo(file, title) |
216 | - album = getTrackInfo(file, album) |
217 | - year = getTrackInfo(file, year) |
218 | - tracknr = getTrackInfo(file, tracknr) |
219 | - length = getTrackInfo(file, length) |
220 | - console.debug("file", "title", "artist", "album", "year", "tracknr", "length") |
221 | - //MetaDB.setSetting("file", "title", "artist", "album", "year", "tracknr", "length") |
222 | - }*/ |
223 | - } |
224 | - |
225 | - |
226 | - width: units.gu(50) |
227 | - height: units.gu(75) |
228 | - |
229 | - Page { |
230 | - id: singleTracksPage |
231 | - |
232 | - // toolbar |
233 | - tools: defaultToolbar |
234 | - |
235 | - Column { |
236 | - anchors.centerIn: parent |
237 | + Settings.setSetting("initialized", "true") |
238 | + Settings.setSetting("currentfolder", folderModel.homePath() + "/Music") |
239 | + } |
240 | + random = Settings.getSetting("shuffle") == "1" |
241 | + filelist.currentIndex = -1 |
242 | + } |
243 | + |
244 | + Page { |
245 | + id: mainpage |
246 | + |
247 | + title: i18n.tr("Music") |
248 | + |
249 | + Component { |
250 | + id: highlight |
251 | + Rectangle { |
252 | + width: 5; height: 40 |
253 | + color: "#DD4814"; |
254 | + Behavior on y { |
255 | + SpringAnimation { |
256 | + spring: 3 |
257 | + damping: 0.2 |
258 | + } |
259 | + } |
260 | + } |
261 | + } |
262 | + |
263 | + ListView { |
264 | + id: filelist |
265 | + width: parent.width |
266 | + height: parent.height - units.gu(8) |
267 | + anchors.top: tracksContext.bottom |
268 | + highlight: highlight |
269 | + highlightFollowsCurrentItem: true |
270 | + model: folderModel |
271 | + delegate: fileDelegate |
272 | + onCountChanged: { |
273 | + filelistCount = filelist.count |
274 | + } |
275 | + onCurrentIndexChanged: { |
276 | + filelistCurrentIndex = filelist.currentIndex |
277 | + console.log("filelist.currentIndex = " + filelist.currentIndex) |
278 | + } |
279 | + |
280 | + Component { |
281 | + id: fileDelegate |
282 | + ListItem.Standard { |
283 | + id: file |
284 | + progression: model.isDir |
285 | + icon: !model.isDir ? (trackCover === "" ? (fileName.match("\\.mp3") ? Qt.resolvedUrl("images/audio-x-mpeg.png") : Qt.resolvedUrl("images/audio-x-vorbis+ogg.png")) : "image://cover-art/"+filePath) : Qt.resolvedUrl("images/folder.png") |
286 | + iconFrame: false |
287 | + Label { |
288 | + id: fileTitle |
289 | + width: 400 |
290 | + wrapMode: Text.Wrap |
291 | + maximumLineCount: 1 |
292 | + font.pixelSize: 16 |
293 | + anchors.left: parent.left |
294 | + anchors.leftMargin: 75 |
295 | + anchors.top: parent.top |
296 | + anchors.topMargin: 5 |
297 | + text: trackTitle == "" ? fileName : trackTitle |
298 | + } |
299 | + Label { |
300 | + id: fileArtistAlbum |
301 | + width: 400 |
302 | + wrapMode: Text.Wrap |
303 | + maximumLineCount: 2 |
304 | + font.pixelSize: 12 |
305 | + anchors.left: parent.left |
306 | + anchors.leftMargin: 75 |
307 | + anchors.top: fileTitle.bottom |
308 | + text: trackArtist == "" ? "" : trackArtist + " - " + trackAlbum |
309 | + } |
310 | + Label { |
311 | + id: fileDuration |
312 | + width: 400 |
313 | + wrapMode: Text.Wrap |
314 | + maximumLineCount: 2 |
315 | + font.pixelSize: 12 |
316 | + anchors.left: parent.left |
317 | + anchors.leftMargin: 75 |
318 | + anchors.top: fileArtistAlbum.bottom |
319 | + visible: false |
320 | + text: "" |
321 | + } |
322 | + |
323 | + onFocusChanged: { |
324 | + if (focus == false) { |
325 | + selected = false |
326 | + } else if (file.progression == false){ |
327 | + selected = false |
328 | + fileArtistAlbumBottom.text = fileArtistAlbum.text |
329 | + fileTitleBottom.text = fileTitle.text |
330 | + fileArtistAlbumBottom_nowplaying.text = trackArtist == "" ? "" : trackArtist + "\n" + trackAlbum |
331 | + fileTitleBottom_nowplaying.text = fileTitle.text |
332 | + iconbottom.source = file.icon |
333 | + iconbottom_nowplaying.source = !model.isDir && trackCover !== "" ? "image://cover-art-full/" + filePath : "images/Blank_album.jpg" |
334 | + } |
335 | + } |
336 | + MouseArea { |
337 | + anchors.fill: parent |
338 | + onDoubleClicked: { |
339 | + } |
340 | + onPressAndHold: { |
341 | + if (!model.isDir) { |
342 | + trackQueue.append({"title": trackTitle, "artist": trackArtist, "file": filePath}) |
343 | + } |
344 | + } |
345 | + onClicked: { |
346 | + if (focus == false) { |
347 | + focus = true |
348 | + } |
349 | + if (model.isDir) { |
350 | + PlayingList.clear() |
351 | + filelist.currentIndex = -1 |
352 | + itemnum = 0 |
353 | + playing = filelist.currentIndex |
354 | + console.log("Stored:" + Settings.getSetting("currentfolder")) |
355 | + folderModel.path = filePath |
356 | + } else { |
357 | + console.log("fileName: " + fileName) |
358 | + if (filelist.currentIndex == index) { |
359 | + if (player.playbackState === MediaPlayer.PlayingState) { |
360 | + playindicator.source = "images/play.png" |
361 | + player.pause() |
362 | + } else if (player.playbackState === MediaPlayer.PausedState) { |
363 | + playindicator.source = "images/pause.png" |
364 | + player.play() |
365 | + } |
366 | + } else { |
367 | + player.stop() |
368 | + player.source = Qt.resolvedUrl(filePath) |
369 | + filelist.currentIndex = index |
370 | + playing = PlayingList.indexOf(filePath) |
371 | + console.log("Playing click: "+player.source) |
372 | + console.log("Index: " + filelist.currentIndex) |
373 | + player.play() |
374 | + playindicator.source = "images/pause.png" |
375 | + } |
376 | + console.log("Source: " + player.source.toString()) |
377 | + console.log("Length: " + trackLength.toString()) |
378 | + } |
379 | + playindicator_nowplaying.source = playindicator.source |
380 | + } |
381 | + } |
382 | + Component.onCompleted: { |
383 | + if (!PlayingList.contains(filePath) && !model.isDir) { |
384 | + console.log("Adding file:" + filePath) |
385 | + PlayingList.addItem(filePath, itemnum) |
386 | + console.log(itemnum) |
387 | + } |
388 | + itemnum++ |
389 | + } |
390 | + } |
391 | + } |
392 | + } |
393 | + |
394 | + // context: albums? tracks? |
395 | + Rectangle { |
396 | + id: appContext |
397 | + anchors.top: mainpage.top |
398 | + height: units.gu(5) |
399 | + width: parent.width |
400 | + color: "#333333" |
401 | + MouseArea { |
402 | + id: tracksContextArea |
403 | + anchors.verticalCenter: parent.verticalCenter |
404 | + anchors.left: parent.left |
405 | + width: units.gu(10) |
406 | + height: units.gu(5) |
407 | + onClicked: { |
408 | + tracksContext.font.underline = true |
409 | + artistsContext.font.underline = false |
410 | + albumsContext.font.underline = false |
411 | + listsContext.font.underline = false |
412 | + } |
413 | + Label { |
414 | + id: tracksContext |
415 | + width: units.gu(15) |
416 | + wrapMode: Text.Wrap |
417 | + color: "#FFFFFF" |
418 | + maximumLineCount: 1 |
419 | + font.pixelSize: 20 |
420 | + anchors.verticalCenter: parent.verticalCenter |
421 | + anchors.left: parent.left |
422 | + anchors.leftMargin: units.gu(1) |
423 | + text: "Music" |
424 | + font.underline: true |
425 | + } |
426 | + } |
427 | + MouseArea { |
428 | + id: artistsContextArea |
429 | + anchors.verticalCenter: parent.verticalCenter |
430 | + anchors.left: tracksContextArea.right |
431 | + width: units.gu(10) |
432 | + height: units.gu(5) |
433 | + onClicked: { |
434 | + tracksContext.font.underline = false |
435 | + artistsContext.font.underline = true |
436 | + albumsContext.font.underline = false |
437 | + listsContext.font.underline = false |
438 | + } |
439 | + Label { |
440 | + id: artistsContext |
441 | + width: units.gu(10) |
442 | + wrapMode: Text.Wrap |
443 | + color: "#FFFFFF" |
444 | + maximumLineCount: 1 |
445 | + font.pixelSize: 20 |
446 | + anchors.verticalCenter: parent.verticalCenter |
447 | + anchors.left: parent.left |
448 | + text: "Artists" |
449 | + } |
450 | + } |
451 | + MouseArea { |
452 | + id: albumsContextArea |
453 | + anchors.verticalCenter: parent.verticalCenter |
454 | + anchors.left: artistsContextArea.right |
455 | + width: units.gu(10) |
456 | + height: units.gu(5) |
457 | + onClicked: { |
458 | + tracksContext.font.underline = false |
459 | + artistsContext.font.underline = false |
460 | + albumsContext.font.underline = true |
461 | + listsContext.font.underline = false |
462 | + } |
463 | + Label { |
464 | + id: albumsContext |
465 | + width: units.gu(15) |
466 | + wrapMode: Text.Wrap |
467 | + color: "#FFFFFF" |
468 | + maximumLineCount: 1 |
469 | + font.pixelSize: 20 |
470 | + anchors.verticalCenter: parent.verticalCenter |
471 | + anchors.left: parent.left |
472 | + text: "Albums" |
473 | + } |
474 | + } |
475 | + MouseArea { |
476 | + id: listsContextArea |
477 | + anchors.verticalCenter: parent.verticalCenter |
478 | + anchors.left: albumsContextArea.right |
479 | + width: units.gu(10) |
480 | + height: units.gu(5) |
481 | + onClicked: { |
482 | + |
483 | + PopupUtils.open(Qt.resolvedUrl("QueueDialog.qml"), settingsArea, |
484 | + { |
485 | + title: i18n.tr("Queue") |
486 | + } ) |
487 | + } |
488 | + Label { |
489 | + id: listsContext |
490 | + width: units.gu(15) |
491 | + wrapMode: Text.Wrap |
492 | + color: "#FFFFFF" |
493 | + maximumLineCount: 1 |
494 | + font.pixelSize: 20 |
495 | + anchors.verticalCenter: parent.verticalCenter |
496 | + anchors.left: parent.left |
497 | + text: "Queue" |
498 | + } |
499 | + } |
500 | + MouseArea { |
501 | + id: settingsArea |
502 | + anchors.verticalCenter: parent.verticalCenter |
503 | + anchors.left: listsContextArea.right |
504 | + anchors.right: parent.right |
505 | + height: units.gu(5) |
506 | + onClicked: { |
507 | + PopupUtils.open(Qt.resolvedUrl("MusicSettings.qml"), settingsArea, |
508 | + { |
509 | + title: i18n.tr("Settings") |
510 | + } ) |
511 | + } |
512 | + Image { |
513 | + id: settingsImage |
514 | + source: "images/settings.png" |
515 | + anchors.left: parent.left |
516 | + anchors.verticalCenter: parent.verticalCenter |
517 | + anchors.leftMargin: units.gu(1) |
518 | + } |
519 | + } |
520 | + |
521 | + } |
522 | + |
523 | + Rectangle { |
524 | + id: playerControls |
525 | + anchors.top: filelist.bottom |
526 | + height: units.gu(8) |
527 | + width: parent.width |
528 | + color: "#333333" |
529 | + UbuntuShape { |
530 | + id: forwardshape |
531 | + height: units.gu(5) |
532 | + width: units.gu(5) |
533 | + anchors.verticalCenter: parent.verticalCenter |
534 | + anchors.right: parent.right |
535 | + anchors.rightMargin: units.gu(2) |
536 | + radius: "none" |
537 | + image: Image { |
538 | + id: forwardindicator |
539 | + source: "images/forward.png" |
540 | + anchors.right: parent.right |
541 | + anchors.centerIn: parent |
542 | + opacity: .7 |
543 | + } |
544 | + MouseArea { |
545 | + anchors.fill: parent |
546 | + onClicked: { |
547 | + playindicator.source = "images/pause.png" |
548 | + playindicator_nowplaying.source = playindicator.source |
549 | + nextSong() |
550 | + } |
551 | + } |
552 | + } |
553 | + UbuntuShape { |
554 | + id: playshape |
555 | + height: units.gu(5) |
556 | + width: units.gu(5) |
557 | + anchors.verticalCenter: parent.verticalCenter |
558 | + anchors.right: forwardshape.left |
559 | + anchors.rightMargin: units.gu(1) |
560 | + radius: "none" |
561 | + image: Image { |
562 | + id: playindicator |
563 | + source: "images/play.png" |
564 | + anchors.right: parent.right |
565 | + anchors.centerIn: parent |
566 | + opacity: .7 |
567 | + } |
568 | + MouseArea { |
569 | + anchors.fill: parent |
570 | + onClicked: { |
571 | + if (player.playbackState === MediaPlayer.PlayingState) { |
572 | + playindicator.source = "images/play.png" |
573 | + player.pause() |
574 | + } else { |
575 | + playindicator.source = "images/pause.png" |
576 | + player.play() |
577 | + } |
578 | + playindicator_nowplaying.source = playindicator.source |
579 | + } |
580 | + } |
581 | + } |
582 | + Image { |
583 | + id: iconbottom |
584 | + source: "" |
585 | + anchors.left: parent.left |
586 | + anchors.top: parent.top |
587 | + anchors.topMargin: units.gu(1) |
588 | + anchors.leftMargin: units.gu(1) |
589 | + |
590 | + MouseArea { |
591 | + anchors.fill: parent |
592 | + onClicked: { |
593 | + pageStack.push(nowPlaying) |
594 | + } |
595 | + } |
596 | + } |
597 | + Label { |
598 | + id: fileTitleBottom |
599 | + width: units.gu(30) |
600 | + wrapMode: Text.Wrap |
601 | + color: "#FFFFFF" |
602 | + maximumLineCount: 1 |
603 | + font.pixelSize: 16 |
604 | + anchors.left: iconbottom.right |
605 | + anchors.top: parent.top |
606 | + anchors.topMargin: units.gu(1) |
607 | + anchors.leftMargin: units.gu(1) |
608 | + text: "" |
609 | + } |
610 | + Label { |
611 | + id: fileArtistAlbumBottom |
612 | + width: units.gu(30) |
613 | + wrapMode: Text.Wrap |
614 | + color: "#FFFFFF" |
615 | + maximumLineCount: 1 |
616 | + font.pixelSize: 12 |
617 | + anchors.left: iconbottom.right |
618 | + anchors.top: fileTitleBottom.bottom |
619 | + anchors.leftMargin: units.gu(1) |
620 | + text: "" |
621 | + } |
622 | + Rectangle { |
623 | + id: fileDurationProgressContainer |
624 | + anchors.top: fileArtistAlbumBottom.bottom |
625 | + anchors.left: iconbottom.right |
626 | + anchors.topMargin: 2 |
627 | + anchors.leftMargin: units.gu(1) |
628 | + width: units.gu(20) |
629 | + color: "#333333" |
630 | + |
631 | + Rectangle { |
632 | + id: fileDurationProgressBackground |
633 | + anchors.top: parent.top |
634 | + anchors.topMargin: 2 |
635 | + height: 1 |
636 | + width: units.gu(20) |
637 | + color: "#FFFFFF" |
638 | + visible: false |
639 | + } |
640 | + Rectangle { |
641 | + id: fileDurationProgress |
642 | + anchors.top: parent.top |
643 | + height: 5 |
644 | + width: 0 |
645 | + color: "#DD4814" |
646 | + } |
647 | + } |
648 | + Label { |
649 | + id: fileDurationBottom |
650 | + anchors.top: fileArtistAlbumBottom.bottom |
651 | + anchors.left: fileDurationProgressContainer.right |
652 | + anchors.leftMargin: units.gu(1) |
653 | + width: units.gu(30) |
654 | + wrapMode: Text.Wrap |
655 | + color: "#FFFFFF" |
656 | + maximumLineCount: 1 |
657 | + font.pixelSize: 12 |
658 | + text: "" |
659 | + } |
660 | + } |
661 | + } |
662 | + |
663 | + Page { |
664 | + id: nowPlaying |
665 | + visible: false |
666 | + |
667 | + Rectangle { |
668 | anchors.fill: parent |
669 | - ListView { |
670 | - id: musicFolder |
671 | - width: parent.width |
672 | - height: parent.height |
673 | - model: folderModel |
674 | - //delegate: databaseDelegate |
675 | - delegate: ListItem.Subtitled { |
676 | - text: fileName |
677 | - subText: "Artist: " // this should be selected from metaDB |
678 | - Loader { |
679 | - id: trackLoad |
680 | - //onLoaded: |
681 | - Component.onCompleted: { |
682 | - console.debug("This one was found: "+index+"; "+fileName) |
683 | - trackQueue.append({"title": playMusic.metaData.title, "artist": playMusic.metaData.albumArtist, "file": filePath}) // just for dev |
684 | - /* Insert them to database |
685 | - // start adding tracks to db |
686 | - title = getTrackInfo(file, title) |
687 | - album = getTrackInfo(file, album) |
688 | - year = getTrackInfo(file, year) |
689 | - tracknr = getTrackInfo(file, tracknr) |
690 | - length = getTrackInfo(file, length) |
691 | - console.debug("file", "title", "artist", "album", "year", "tracknr", "length") |
692 | - //MetaDB.setSetting("file", "title", "artist", "album", "year", "tracknr", "length") |
693 | - */ |
694 | + height: units.gu(10) |
695 | + color: "#333333" |
696 | + Column { |
697 | + anchors.fill: parent |
698 | + anchors.bottomMargin: units.gu(10) |
699 | + |
700 | + UbuntuShape { |
701 | + id: forwardshape_nowplaying |
702 | + height: 50 |
703 | + width: 50 |
704 | + anchors.bottom: parent.bottom |
705 | + anchors.left: playshape_nowplaying.right |
706 | + anchors.leftMargin: units.gu(2) |
707 | + radius: "none" |
708 | + image: Image { |
709 | + id: forwardindicator_nowplaying |
710 | + source: "images/forward.png" |
711 | + anchors.right: parent.right |
712 | + anchors.bottom: parent.bottom |
713 | + opacity: .7 |
714 | + } |
715 | + MouseArea { |
716 | + anchors.fill: parent |
717 | + onClicked: { |
718 | + playindicator.source = "images/pause.png" |
719 | + playindicator_nowplaying.source = playindicator.source |
720 | + nextSong() |
721 | + } |
722 | + } |
723 | + } |
724 | + UbuntuShape { |
725 | + id: playshape_nowplaying |
726 | + height: 50 |
727 | + width: 50 |
728 | + anchors.bottom: parent.bottom |
729 | + anchors.horizontalCenter: parent.horizontalCenter |
730 | + radius: "none" |
731 | + image: Image { |
732 | + id: playindicator_nowplaying |
733 | + source: "images/play.png" |
734 | + anchors.right: parent.right |
735 | + anchors.bottom: parent.bottom |
736 | + opacity: .7 |
737 | + } |
738 | + MouseArea { |
739 | + anchors.fill: parent |
740 | + onClicked: { |
741 | + if (player.playbackState === MediaPlayer.PlayingState) { |
742 | + playindicator.source = "images/play.png" |
743 | + player.pause() |
744 | + } else { |
745 | + playindicator.source = "images/pause.png" |
746 | + player.play() |
747 | } |
748 | - } |
749 | - |
750 | - onClicked: { |
751 | - playMusic.source = filePath |
752 | - playMusic.play() |
753 | - console.debug('Debug: User pressed '+filePath) |
754 | - trackInfo.text = playMusic.metaData.albumArtist+" - "+playMusic.metaData.title // show track meta data |
755 | - // cool animation |
756 | - } |
757 | - onPressAndHold: { |
758 | - console.debug('Debug: '+filePath+' added to queue.') |
759 | - trackQueue.append({"title": playMusic.metaData.title, "artist": playMusic.metaData.albumArtist, "file": filePath}) |
760 | - // cool animation |
761 | - } |
762 | + playindicator_nowplaying.source = playindicator.source |
763 | + } |
764 | + } |
765 | + } |
766 | + UbuntuShape { |
767 | + id: backshape_nowplaying |
768 | + height: 50 |
769 | + width: 50 |
770 | + anchors.bottom: parent.bottom |
771 | + anchors.right: playshape_nowplaying.left |
772 | + anchors.rightMargin: units.gu(2) |
773 | + radius: "none" |
774 | + image: Image { |
775 | + id: backindicator_nowplaying |
776 | + source: "images/back.png" |
777 | + anchors.right: parent.right |
778 | + anchors.bottom: parent.bottom |
779 | + opacity: .7 |
780 | + } |
781 | + MouseArea { |
782 | + anchors.fill: parent |
783 | + onClicked: { |
784 | + playindicator.source = "images/pause.png" |
785 | + playindicator_nowplaying.source = playindicator.source |
786 | + getSong(-1) |
787 | + } |
788 | + } |
789 | + } |
790 | + |
791 | + Image { |
792 | + id: iconbottom_nowplaying |
793 | + source: "" |
794 | + width: 300 |
795 | + height: 300 |
796 | + anchors.horizontalCenter: parent.horizontalCenter |
797 | + anchors.top: parent.top |
798 | + anchors.topMargin: units.gu(1) |
799 | + anchors.leftMargin: units.gu(1) |
800 | + |
801 | + MouseArea { |
802 | + anchors.fill: parent |
803 | + onClicked: { |
804 | + pageStack.pop(nowPlaying) |
805 | + } |
806 | + } |
807 | + } |
808 | + Label { |
809 | + id: fileTitleBottom_nowplaying |
810 | + width: units.gu(30) |
811 | + wrapMode: Text.Wrap |
812 | + color: "#FFFFFF" |
813 | + maximumLineCount: 1 |
814 | + font.pixelSize: 24 |
815 | + anchors.top: iconbottom_nowplaying.bottom |
816 | + anchors.topMargin: units.gu(2) |
817 | + anchors.left: parent.left |
818 | + anchors.leftMargin: units.gu(2) |
819 | + text: "" |
820 | + } |
821 | + Label { |
822 | + id: fileArtistAlbumBottom_nowplaying |
823 | + width: units.gu(30) |
824 | + wrapMode: Text.Wrap |
825 | + color: "#FFFFFF" |
826 | + maximumLineCount: 2 |
827 | + font.pixelSize: 16 |
828 | + anchors.left: parent.left |
829 | + anchors.top: fileTitleBottom_nowplaying.bottom |
830 | + anchors.leftMargin: units.gu(2) |
831 | + text: "" |
832 | + } |
833 | + Rectangle { |
834 | + id: fileDurationProgressContainer_nowplaying |
835 | + anchors.top: fileArtistAlbumBottom_nowplaying.bottom |
836 | + anchors.left: parent.left |
837 | + anchors.topMargin: units.gu(2) |
838 | + anchors.leftMargin: units.gu(2) |
839 | + width: units.gu(40) |
840 | + color: "#333333" |
841 | + |
842 | + Rectangle { |
843 | + id: fileDurationProgressBackground_nowplaying |
844 | + anchors.top: parent.top |
845 | + anchors.topMargin: 4 |
846 | + height: 1 |
847 | + width: units.gu(40) |
848 | + color: "#FFFFFF" |
849 | + visible: false |
850 | + } |
851 | + Rectangle { |
852 | + id: fileDurationProgress_nowplaying |
853 | + anchors.top: parent.top |
854 | + height: 8 |
855 | + width: 0 |
856 | + color: "#DD4814" |
857 | + } |
858 | + } |
859 | + Label { |
860 | + id: fileDurationBottom_nowplaying |
861 | + anchors.top: fileDurationProgressContainer_nowplaying.bottom |
862 | + anchors.left: parent.left |
863 | + anchors.topMargin: units.gu(2) |
864 | + anchors.leftMargin: units.gu(2) |
865 | + width: units.gu(30) |
866 | + wrapMode: Text.Wrap |
867 | + color: "#FFFFFF" |
868 | + maximumLineCount: 1 |
869 | + font.pixelSize: 16 |
870 | + text: "" |
871 | } |
872 | } |
873 | } |
874 | - |
875 | } |
876 | - |
877 | } |
878 | |
879 | === modified file 'QueueDialog.qml' |
880 | --- QueueDialog.qml 2013-05-31 14:58:23 +0000 |
881 | +++ QueueDialog.qml 2013-06-05 04:48:28 +0000 |
882 | @@ -3,6 +3,7 @@ |
883 | * |
884 | * Authors: |
885 | * Daniel Holm <d.holmen@gmail.com> |
886 | + * Victor Thompson <victor.thompson@gmail.com> |
887 | * |
888 | * This program is free software; you can redistribute it and/or modify |
889 | * it under the terms of the GNU General Public License as published by |
890 | @@ -32,8 +33,7 @@ |
891 | height: units.gu(50) |
892 | model: trackQueue |
893 | delegate: ListItem.Standard { |
894 | - //text: artist+" - "+title |
895 | - text: file |
896 | + text: artist+" - "+title |
897 | removable: true |
898 | onClicked: { |
899 | console.debug("Debug: Play "+file+" instead - now.") |
900 | @@ -50,7 +50,7 @@ |
901 | // Clean whole queue button |
902 | Button { |
903 | text: i18n.tr("Clear") |
904 | - color: "orange" |
905 | + color: "#DD4814" |
906 | onClicked: { |
907 | console.debug("Debug: Track queue cleared.") |
908 | trackQueue.clear() |
909 | @@ -61,7 +61,7 @@ |
910 | // close dialog button |
911 | Button { |
912 | text: i18n.tr("Close") |
913 | - color: "red" |
914 | + color: "#DD4814" |
915 | onClicked: { |
916 | PopupUtils.close(queueDialog) |
917 | } |
918 | |
919 | === removed file 'Toolbar.qml' |
920 | --- Toolbar.qml 2013-05-08 21:53:49 +0000 |
921 | +++ Toolbar.qml 1970-01-01 00:00:00 +0000 |
922 | @@ -1,103 +0,0 @@ |
923 | -/* |
924 | - * Copyleft Daniel Holm. |
925 | - * |
926 | - * Authors: |
927 | - * Daniel Holm <d.holmen@gmail.com> |
928 | - * |
929 | - * This program is free software; you can redistribute it and/or modify |
930 | - * it under the terms of the GNU General Public License as published by |
931 | - * the Free Software Foundation; version 3. |
932 | - * |
933 | - * This program is distributed in the hope that it will be useful, |
934 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
935 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
936 | - * GNU General Public License for more details. |
937 | - * |
938 | - * You should have received a copy of the GNU General Public License |
939 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
940 | - */ |
941 | - |
942 | -import QtQuick 2.0 |
943 | -import Ubuntu.Components 0.1 |
944 | -import Ubuntu.Components.ListItems 0.1 as ListItem |
945 | -import Ubuntu.Components.Popups 0.1 |
946 | - |
947 | -Component { |
948 | - // Share |
949 | - Action { |
950 | - id: shareTrack |
951 | - objectName: "share" |
952 | - |
953 | - iconSource: Qt.resolvedUrl("images/icon_share@20.png") |
954 | - text: i18n.tr("Share") |
955 | - |
956 | - onTriggered: { |
957 | - console.debug('Debug: Share pressed') |
958 | - } |
959 | - } |
960 | - |
961 | - // prevous track |
962 | - Action { |
963 | - id: prevTrack |
964 | - objectName: "prev" |
965 | - |
966 | - iconSource: Qt.resolvedUrl("images/prev.png") |
967 | - text: i18n.tr("Previous") |
968 | - |
969 | - onTriggered: { |
970 | - console.debug('Debug: Prev track pressed') |
971 | - } |
972 | - } |
973 | - |
974 | - // Play |
975 | - Action { |
976 | - id: playTrack |
977 | - objectName: "play" |
978 | - |
979 | - iconSource: Qt.resolvedUrl("images/icon_play@20.png") |
980 | - text: i18n.tr("Play") |
981 | - |
982 | - onTriggered: { |
983 | - //trackStatus: 'pause' // this changes on press |
984 | - onTrackStatusChange(playTrack.text) |
985 | - } |
986 | - } |
987 | - |
988 | - // Next track |
989 | - Action { |
990 | - id: nextTrack |
991 | - objectName: "next" |
992 | - |
993 | - iconSource: Qt.resolvedUrl("images/next.png") |
994 | - text: i18n.tr("Next") |
995 | - |
996 | - onTriggered: { |
997 | - console.debug('Debug: next track pressed') |
998 | - } |
999 | - } |
1000 | - |
1001 | - // Queue |
1002 | - Action { |
1003 | - id: trackQueue |
1004 | - objectName: "queuelist" |
1005 | - iconSource: Qt.resolvedUrl("images/icon_settings@20.png") |
1006 | - text: i18n.tr("Queue") |
1007 | - onTriggered: { |
1008 | - PopupUtils.open(queueDialog, trackQueue) |
1009 | - } |
1010 | - } |
1011 | - |
1012 | - // Settings |
1013 | - Action { |
1014 | - objectName: "settings" |
1015 | - |
1016 | - iconSource: Qt.resolvedUrl("images/icon_settings@20.png") |
1017 | - text: i18n.tr("Settings") |
1018 | - |
1019 | - onTriggered: { |
1020 | - console.debug('Debug: Settings pressed') |
1021 | - // show settings page |
1022 | - //page: MusicSettings { id: musicSettings } |
1023 | - } |
1024 | - } |
1025 | -} |
1026 | |
1027 | === modified file 'debian/changelog' |
1028 | --- debian/changelog 2013-06-01 01:05:45 +0000 |
1029 | +++ debian/changelog 2013-06-05 04:48:28 +0000 |
1030 | @@ -1,5 +1,11 @@ |
1031 | +music-app (0.2) raring; urgency=low |
1032 | + |
1033 | + * Merge of Daniel's and Victor's code |
1034 | + |
1035 | + -- Victor Thompson <victor.thompson@gmail.com> Tue, 04 June 2013 11:45:00 -0400 |
1036 | + |
1037 | music-app (0.1) raring; urgency=low |
1038 | |
1039 | * Initial Release. |
1040 | |
1041 | - -- "Michael <mhall119@ubuntu.com> Thu, 23 May 2013 17:10:45 -0400 |
1042 | + -- Michael <mhall119@ubuntu.com> Thu, 23 May 2013 17:10:45 -0400 |
1043 | |
1044 | === modified file 'debian/install' |
1045 | --- debian/install 2013-06-03 17:43:53 +0000 |
1046 | +++ debian/install 2013-06-05 04:48:28 +0000 |
1047 | @@ -1,4 +1,3 @@ |
1048 | -Toolbar.qml /usr/share/music-app |
1049 | MusicSettings.qml /usr/share/music-app |
1050 | music-app.qml /usr/share/music-app |
1051 | QueueDialog.qml /usr/share/music-app |
1052 | @@ -16,5 +15,14 @@ |
1053 | images/icon_settings@20.png /usr/share/music-app |
1054 | images/music.png /usr/share/music-app |
1055 | images/icon_play@20.png /usr/share/music-app |
1056 | +images/settings@8.png /usr/share/music-app |
1057 | +images/play.png /usr/share/music-app |
1058 | +images/pause.png /usr/share/music-app |
1059 | +images/forward.png /usr/share/music-app |
1060 | +images/Blank_album.jpg /usr/share/music-app |
1061 | +images/back.png /usr/share/music-app |
1062 | +images/audio-x-mpeg.png /usr/share/music-app |
1063 | +images/audio-x-vorbis+ogg.png /usr/share/music-app |
1064 | +playing-list.js /usr/share/music-app |
1065 | meta-database.js /usr/share/music-app |
1066 | music-app.desktop /usr/share/applications |
1067 | |
1068 | === added file 'images/Blank_album.jpg' |
1069 | Binary files images/Blank_album.jpg 1970-01-01 00:00:00 +0000 and images/Blank_album.jpg 2013-06-05 04:48:28 +0000 differ |
1070 | === added file 'images/audio-x-mpeg.png' |
1071 | Binary files images/audio-x-mpeg.png 1970-01-01 00:00:00 +0000 and images/audio-x-mpeg.png 2013-06-05 04:48:28 +0000 differ |
1072 | === added file 'images/audio-x-vorbis+ogg.png' |
1073 | Binary files images/audio-x-vorbis+ogg.png 1970-01-01 00:00:00 +0000 and images/audio-x-vorbis+ogg.png 2013-06-05 04:48:28 +0000 differ |
1074 | === added file 'images/back.png' |
1075 | Binary files images/back.png 1970-01-01 00:00:00 +0000 and images/back.png 2013-06-05 04:48:28 +0000 differ |
1076 | === added file 'images/forward.png' |
1077 | Binary files images/forward.png 1970-01-01 00:00:00 +0000 and images/forward.png 2013-06-05 04:48:28 +0000 differ |
1078 | === added file 'images/pause.png' |
1079 | Binary files images/pause.png 1970-01-01 00:00:00 +0000 and images/pause.png 2013-06-05 04:48:28 +0000 differ |
1080 | === added file 'images/play.png' |
1081 | Binary files images/play.png 1970-01-01 00:00:00 +0000 and images/play.png 2013-06-05 04:48:28 +0000 differ |
1082 | === added file 'images/settings@8.png' |
1083 | Binary files images/settings@8.png 1970-01-01 00:00:00 +0000 and images/settings@8.png 2013-06-05 04:48:28 +0000 differ |
1084 | === modified file 'music-app.qml' |
1085 | --- music-app.qml 2013-06-03 17:43:53 +0000 |
1086 | +++ music-app.qml 2013-06-05 04:48:28 +0000 |
1087 | @@ -3,6 +3,7 @@ |
1088 | * |
1089 | * Authors: |
1090 | * Daniel Holm <d.holmen@gmail.com> |
1091 | + * Victor Thompson <victor.thompson@gmail.com> |
1092 | * |
1093 | * This program is free software; you can redistribute it and/or modify |
1094 | * it under the terms of the GNU General Public License as published by |
1095 | @@ -22,11 +23,12 @@ |
1096 | import Ubuntu.Components.ListItems 0.1 |
1097 | import Ubuntu.Components.Popups 0.1 |
1098 | import Ubuntu.Components.ListItems 0.1 as ListItem |
1099 | -import Qt.labs.folderlistmodel 1.0 |
1100 | +import org.nemomobile.folderlistmodel 1.0 |
1101 | import QtMultimedia 5.0 |
1102 | import QtQuick.LocalStorage 2.0 |
1103 | import "settings.js" as Settings |
1104 | -import "meta-database.js" as MetaDatabase |
1105 | +import "meta-database.js" as Library |
1106 | +import "playing-list.js" as PlayingList |
1107 | |
1108 | MainView { |
1109 | objectName: i18n.tr("mainView") |
1110 | @@ -34,156 +36,76 @@ |
1111 | |
1112 | width: units.gu(50) |
1113 | height: units.gu(75) |
1114 | + Component.onCompleted: { |
1115 | + header.visible = false |
1116 | + } |
1117 | + |
1118 | |
1119 | // VARIABLES |
1120 | property string musicName: i18n.tr("Music") |
1121 | property string musicDir: "" |
1122 | - property string shuffleState: "" |
1123 | - property string trackStatus: "stopped" |
1124 | property string appVersion: '0.5.2' |
1125 | + property int playing: 0 |
1126 | + property int itemnum: 0 |
1127 | + property bool random: false |
1128 | + property string artist |
1129 | + property string album |
1130 | + property string song |
1131 | + property string tracktitle |
1132 | |
1133 | // FUNCTIONS |
1134 | - |
1135 | - // digg deeper in the music folder |
1136 | - function subDirCheck(directory) { |
1137 | - // populate listmodel with meta data of tracks |
1138 | - } |
1139 | - |
1140 | - // What is the state of the playback? |
1141 | - function stateChange() { |
1142 | - // state was stopped (0) |
1143 | - if (playMusic.playbackState == "0") { |
1144 | - console.debug("Debug: Music was stopped. Playing") |
1145 | - beenStopped() // run stop function |
1146 | - playMusic.play() // then play |
1147 | - } |
1148 | - |
1149 | - // if state was playing (1) |
1150 | - else if (playMusic.playbackState == "1") { |
1151 | - console.debug("Debug: Track was playing. Pause") |
1152 | - playMusic.pause() // pause the music then |
1153 | - } |
1154 | - |
1155 | - // if state is paused (2) |
1156 | - else if (playMusic.playbackState == "2") { |
1157 | - console.debug("Debug: Track was paused. Playing") |
1158 | - playMusic.play() // resume then |
1159 | - } |
1160 | - |
1161 | - updateUI() |
1162 | - } |
1163 | - |
1164 | - // stop function |
1165 | - function beenStopped() { |
1166 | - console.debug("Debug: has a track been played before or did I just start?") |
1167 | - |
1168 | - // track was just paused or stopped. Resume previous track |
1169 | - if (playMusic.source != "") { |
1170 | - console.debug("Debug: Resume previous song: "+playMusic.source) |
1171 | - |
1172 | - updateUI() |
1173 | - } |
1174 | - |
1175 | - // app just started, play random or first track in list, depending on shuffle on or off |
1176 | - else { |
1177 | - // is shuffle on? |
1178 | - // if shuffle on { |
1179 | - //} |
1180 | - // Shuffle not activated |
1181 | - //else { |
1182 | - playMusic.source = trackQueue.get(0).file // this should play a dynamic track |
1183 | - console.debug("Debug: First song is "+trackQueue.get(0).file) |
1184 | - console.debug("Debug: I was just started. Play random track: "+playMusic.source) |
1185 | - |
1186 | - updateUI() |
1187 | - //} |
1188 | - } |
1189 | - } |
1190 | - |
1191 | - // previous and next track function |
1192 | - function nextTrack() { |
1193 | - //check if any queued songs |
1194 | - // if there are, play them |
1195 | - if (trackQueue > 1) { |
1196 | - console.debug() // print next songs filename |
1197 | - playMusic.source = trackQueue.get(0).file |
1198 | - playMusic.play() |
1199 | - removedTrackQueue.append({"title": trackQueue.get(0).title, "artist": trackQueue.get(0).artist, "file": trackQueue.get(0).file}) // move the track to a list of preious tracks |
1200 | - trackQueue.remove(index) // remove the track from queue |
1201 | - |
1202 | - updateUI() |
1203 | - } |
1204 | - |
1205 | - // if not, play another |
1206 | - else { |
1207 | - |
1208 | - // if shuffle, play random |
1209 | - if (settings.shuffle == 1) { |
1210 | - updateUI() |
1211 | - } |
1212 | - |
1213 | - // if not shuffle, play next |
1214 | - else { |
1215 | - console.debug() // print next songs filename |
1216 | - playMusic.source = trackQueue.get(0).file |
1217 | - playMusic.play() |
1218 | - removedTrackQueue.append({"title": trackQueue.get(0).title, "artist": trackQueue.get(0).artist, "file": trackQueue.get(0).file}) // move the track to a list of preious tracks |
1219 | - trackQueue.remove(index) // remove the track from queue |
1220 | - |
1221 | - updateUI() |
1222 | - } |
1223 | - } |
1224 | - } |
1225 | - |
1226 | - function previousTrack() { |
1227 | - console.debug("Debug: Previous track was "+removedTrackQueue.get(removedTrackQueue.count).file) |
1228 | - // play the previous track |
1229 | - playMusic.source = removedTrackQueue.get(removedTrackQueue.count).file |
1230 | - playMusic.play() |
1231 | - |
1232 | - updateUI() |
1233 | - } |
1234 | - |
1235 | - // Get song title |
1236 | - function getTrackInfo(source, type) { |
1237 | - console.debug('Debug: Got it. Trying to get meta data from: '+source) // debug |
1238 | - musicInfo.source = source |
1239 | - musicInfo.pause() |
1240 | - |
1241 | - // if title |
1242 | - if (type == "title") { |
1243 | - return musicInfo.metaData.title |
1244 | - } |
1245 | - |
1246 | - // if artist |
1247 | - else if (type == "artist") { |
1248 | - return musicInfo.metaData.albumArtist |
1249 | - } |
1250 | - |
1251 | - // if album |
1252 | - else if (type == "album") { |
1253 | - return musicInfo.metaData.albumTitle |
1254 | - } |
1255 | - |
1256 | - // year |
1257 | - else if (type == "year") { |
1258 | - return musicInfo.metaData.year |
1259 | - } |
1260 | - |
1261 | - // cover |
1262 | - else if (type == "cover") { |
1263 | - // download cover art from last.fm |
1264 | - // save the file in a app dir in HOME |
1265 | - // return the value of the cover art file |
1266 | - } |
1267 | - |
1268 | - // tracknr |
1269 | - else if (type == "tracknr") { |
1270 | - } |
1271 | - |
1272 | - // lenght |
1273 | - else if (type == "length") { |
1274 | - } |
1275 | + function previousSong() { |
1276 | + getSong(-1) |
1277 | + } |
1278 | + function nextSong() { |
1279 | + getSong(1) |
1280 | + } |
1281 | + |
1282 | + function getSong(direction) { |
1283 | + if (random) { |
1284 | + var now = new Date(); |
1285 | + var seed = now.getSeconds(); |
1286 | + do { |
1287 | + var num = (Math.floor((PlayingList.size()) * Math.random(seed))); |
1288 | + console.log(num) |
1289 | + console.log(playing) |
1290 | + } while (num == playing && PlayingList.size() > 0) |
1291 | + player.source = Qt.resolvedUrl(PlayingList.getList()[num]) |
1292 | + musicTracksPage.filelistCurrentIndex = PlayingList.at(num) |
1293 | + playing = num |
1294 | + console.log("MediaPlayer statusChanged, currentIndex: " + musicTracksPage.filelistCurrentIndex) |
1295 | + } else { |
1296 | + if ((playing < PlayingList.size() - 1 && direction === 1 ) |
1297 | + || (playing > 0 && direction === -1)) { |
1298 | + console.log("playing: " + playing) |
1299 | + console.log("filelistCount: " + musicTracksPage.filelistCount) |
1300 | + console.log("PlayingList.size(): " + PlayingList.size()) |
1301 | + playing += direction |
1302 | + if (playing === 0) { |
1303 | + musicTracksPage.filelistCurrentIndex = playing + (itemnum - PlayingList.size()) |
1304 | + } else { |
1305 | + musicTracksPage.filelistCurrentIndex += direction |
1306 | + } |
1307 | + player.source = Qt.resolvedUrl(PlayingList.getList()[playing]) |
1308 | + } else if(direction === 1) { |
1309 | + console.log("playing: " + playing) |
1310 | + console.log("filelistCount: " + musicTracksPage.filelistCount) |
1311 | + console.log("PlayingList.size(): " + PlayingList.size()) |
1312 | + playing = 0 |
1313 | + musicTracksPage.filelistCurrentIndex = playing + (musicTracksPage.filelistCount - PlayingList.size()) |
1314 | + player.source = Qt.resolvedUrl(PlayingList.getList()[playing]) |
1315 | + } else if(direction === -1) { |
1316 | + console.log("playing: " + playing) |
1317 | + console.log("filelistCount: " + musicTracksPage.filelistCount) |
1318 | + console.log("PlayingList.size(): " + PlayingList.size()) |
1319 | + playing = PlayingList.size() - 1 |
1320 | + musicTracksPage.filelistCurrentIndex = playing + (musicTracksPage.filelistCount - PlayingList.size()) |
1321 | + player.source = Qt.resolvedUrl(PlayingList.getList()[playing]) |
1322 | + } |
1323 | + console.log("MediaPlayer statusChanged, currentIndex: " + musicTracksPage.filelistCurrentIndex) |
1324 | + } |
1325 | + console.log("Playing: "+player.source) |
1326 | + player.play() |
1327 | } |
1328 | |
1329 | // add track to database |
1330 | @@ -198,67 +120,30 @@ |
1331 | //length = |
1332 | |
1333 | // push to database |
1334 | - MetaDatabase.setMetadata(track, title, artist, album, cover, year, tracknr, length) |
1335 | - } |
1336 | - |
1337 | - // progressbar |
1338 | - function setProgressbar() { |
1339 | - console.debug("Debug: change progressvalue to "+playMusic.duration) |
1340 | - trackProgress.maximumValue = playMusic.duration |
1341 | - } |
1342 | - |
1343 | - // update the UI things with meta data from track |
1344 | - function updateUI() { |
1345 | - playinTab.title = playMusic.metaData.title // show track title in tab header |
1346 | - playTrack.iconSource = Qt.resolvedUrl("images/icon_pause@20.png") // change toolbar icon |
1347 | - playTrack.text = i18n.tr("Pause") // change toolbar text |
1348 | - trackInfo.text = playMusic.metaData.albumArtist+" - "+playMusic.metaData.title // show track meta data |
1349 | -// coverArt.source = "HOMEDIR/.music-app/coverart/"+MetaDatabase.getMetadata(playMusic.source,"cover") // get cover art filename |
1350 | - |
1351 | - setProgressbar() // set progressbar |
1352 | - |
1353 | - console.debug("Debug: UI updated.") |
1354 | - } |
1355 | - |
1356 | - // Music stuff |
1357 | - Audio { |
1358 | - id: playMusic |
1359 | - source: "" |
1360 | - /* |
1361 | + Library.setMetadata(track, title, artist, album, cover, year, tracknr, length) |
1362 | + } |
1363 | + |
1364 | + MediaPlayer { |
1365 | + id: player |
1366 | + muted: false |
1367 | onStatusChanged: { |
1368 | - if (status === Audio.EndOfMedia || 7 ) { |
1369 | - console.log("Debug: Track ended. Play next.") //debug |
1370 | - //nextTrack() |
1371 | - } |
1372 | - else { |
1373 | - console.log("the Music Players status = " + playMusic.status) |
1374 | + if (status == MediaPlayer.EndOfMedia) { |
1375 | + nextSong() |
1376 | } |
1377 | - }*/ |
1378 | - } |
1379 | - |
1380 | - // while playing |
1381 | - Connections { |
1382 | - target: playMusic |
1383 | - onPlaying: { |
1384 | - trackProgress.value = playMusic.position |
1385 | - console.debug("Debug: change position to "+playMusic.position) |
1386 | - } |
1387 | - } |
1388 | - |
1389 | - // get file meta data |
1390 | - Audio { |
1391 | - id: musicInfo |
1392 | - source: "" |
1393 | - volume: 0.0 |
1394 | - //Keys.onSpacePressed: stateChange() |
1395 | + } |
1396 | + |
1397 | + onPositionChanged: { |
1398 | + musicTracksPage.needsUpdate = true |
1399 | + } |
1400 | } |
1401 | |
1402 | // set the folder from where the music is |
1403 | FolderListModel { |
1404 | id: folderModel |
1405 | - folder: musicDir |
1406 | - showDirs: false |
1407 | - nameFilters: ["*.ogg","*.mp3","*.oga","*.wav"] |
1408 | + showDirectories: false |
1409 | + filterDirectories: false |
1410 | + nameFilters: ["*.mp3", "*.ogg", "*.flac", "*.wav", "*.oga"] |
1411 | + path: Settings.getSetting("initialized") === "true" && Settings.getSetting("currentfolder") !== "" ? Settings.getSetting("currentfolder") : homePath() + "/Music" |
1412 | } |
1413 | |
1414 | /* this is how a queue looks like |
1415 | @@ -283,244 +168,6 @@ |
1416 | id: singleTracks |
1417 | } |
1418 | |
1419 | - // reusable toolbar |
1420 | - ToolbarActions { |
1421 | - id: defaultToolbar |
1422 | - |
1423 | - // Share |
1424 | - Action { |
1425 | - id: shareTrack |
1426 | - objectName: "share" |
1427 | - |
1428 | - iconSource: Qt.resolvedUrl("images/icon_share@20.png") |
1429 | - text: i18n.tr("Share") |
1430 | - |
1431 | - onTriggered: { |
1432 | - console.debug('Debug: Share pressed') |
1433 | - // just to debug other stuff for a while |
1434 | - console.debug("Debug: change progress to "+playMusic.position) |
1435 | - trackProgress.value = playMusic.position |
1436 | - } |
1437 | - } |
1438 | - |
1439 | - // prevous track |
1440 | - Action { |
1441 | - id: prevTrack |
1442 | - objectName: "prev" |
1443 | - |
1444 | - iconSource: Qt.resolvedUrl("images/icon_prev@20.png") |
1445 | - text: i18n.tr("Previous") |
1446 | - |
1447 | - onTriggered: { |
1448 | - console.debug('Debug: Prev track pressed') |
1449 | - //console.debug(removedTrackQueue.get(0).file) // print next songs filename |
1450 | - //playMusic.source = removedTrackQueue.get(0).file |
1451 | - //playMusic.play() |
1452 | - previousTrack() |
1453 | - } |
1454 | - } |
1455 | - |
1456 | - // Play |
1457 | - Action { |
1458 | - id: playTrack |
1459 | - objectName: "play" |
1460 | - |
1461 | - iconSource: Qt.resolvedUrl("images/icon_play@20.png") |
1462 | - text: i18n.tr("Play") |
1463 | - |
1464 | - onTriggered: { |
1465 | - console.debug("Debug: "+trackStatus+" pressed in toolbar.") |
1466 | - console.debug(playMusic.playbackState) |
1467 | - stateChange() |
1468 | - } |
1469 | - } |
1470 | - |
1471 | - // Next track |
1472 | - Action { |
1473 | - id: nextTrack |
1474 | - objectName: "next" |
1475 | - |
1476 | - iconSource: Qt.resolvedUrl("images/icon_next@20.png") |
1477 | - text: i18n.tr("Next") |
1478 | - |
1479 | - onTriggered: { |
1480 | - console.debug('Debug: next track pressed') |
1481 | - console.debug(trackQueue.get(0).file) // print next songs filename |
1482 | - playMusic.source = trackQueue.get(0).file |
1483 | - playMusic.play() |
1484 | - |
1485 | - // move track, which has been played from queue, to old queue so that prev button works |
1486 | - removedTrackQueue.append({"title": trackQueue.get(0).title, "artist": trackQueue.get(0).artist, "file": trackQueue.get(0).file}) |
1487 | - trackQueue.remove(0) |
1488 | - } |
1489 | - } |
1490 | - |
1491 | - // Queue |
1492 | - Action { |
1493 | - id: trackQueueAction |
1494 | - objectName: "queuelist" |
1495 | - iconSource: Qt.resolvedUrl("images/icon_settings@20.png") |
1496 | - text: i18n.tr("Queue") |
1497 | - onTriggered: { |
1498 | - PopupUtils.open(Qt.resolvedUrl("QueueDialog.qml"), pageLayout, |
1499 | - { |
1500 | - title: i18n.tr("Queue") |
1501 | - } ) |
1502 | - } |
1503 | - } |
1504 | - |
1505 | - // Settings |
1506 | - Action { |
1507 | - id: settingsAction |
1508 | - objectName: "settings" |
1509 | - |
1510 | - iconSource: Qt.resolvedUrl("images/icon_settings@20.png") |
1511 | - text: i18n.tr("Settings") |
1512 | - |
1513 | - onTriggered: { |
1514 | - console.debug('Debug: Settings pressed') |
1515 | - // show settings page (not yet implemented) |
1516 | - //dialog |
1517 | - PopupUtils.open(Qt.resolvedUrl("MusicSettings.qml"), pageLayout, |
1518 | - { |
1519 | - title: i18n.tr("Settings") |
1520 | - } ) |
1521 | - } |
1522 | - } |
1523 | - } |
1524 | - |
1525 | - Tabs { |
1526 | - id: tabs |
1527 | - anchors.fill: parent |
1528 | - |
1529 | - // First tab begins here - should be the primary tab |
1530 | - Tab { |
1531 | - id: playinTab |
1532 | - objectName: "Tab1" |
1533 | - |
1534 | - title: musicName |
1535 | - |
1536 | - // Tab content begins here |
1537 | - page: Page { |
1538 | - id: playingPage |
1539 | - |
1540 | - // toolbar |
1541 | - tools: defaultToolbar |
1542 | - |
1543 | - Column { |
1544 | - id: pageLayout |
1545 | - |
1546 | - spacing: units.gu(1) |
1547 | - |
1548 | - Column { |
1549 | - spacing: units.gu(1) |
1550 | - // Album cover here |
1551 | - UbuntuShape { |
1552 | - id: trackCoverArt |
1553 | - width: units.gu(50) |
1554 | - height: units.gu(50) |
1555 | - gradientColor: "blue" // test |
1556 | - image: Image { |
1557 | - id: coverArt |
1558 | - source: "images/music.png" |
1559 | - } |
1560 | - } |
1561 | - /*onClicked: { |
1562 | - playMusic.pause() |
1563 | - } |
1564 | - onDoubbleTap: { |
1565 | - nextTrack() |
1566 | - } |
1567 | - onPressAndHold: { |
1568 | - playMusic.stop() |
1569 | - }*/ |
1570 | - } |
1571 | - |
1572 | - // track progress |
1573 | - Column { |
1574 | - width: units.gu(50) |
1575 | - ProgressBar { |
1576 | - id: trackProgress |
1577 | - minimumValue: 0 |
1578 | - maximumValue: 100 |
1579 | - value: 0 |
1580 | - } |
1581 | - } |
1582 | - |
1583 | - // Track info |
1584 | - Column { |
1585 | - spacing: units.gu(1) |
1586 | - Label { |
1587 | - id: trackInfo |
1588 | - text: "Stopped. Press play." |
1589 | - //subText: "Artist: + Year:" |
1590 | - } |
1591 | - } |
1592 | - } |
1593 | - |
1594 | - |
1595 | - } |
1596 | - } |
1597 | - |
1598 | - |
1599 | - // Second tab begins here - artists here |
1600 | - Tab { |
1601 | - objectName: "Artists Tab" |
1602 | - |
1603 | - title: i18n.tr("Artists") |
1604 | - page: Page { |
1605 | - anchors.margins: units.gu(2) |
1606 | - |
1607 | - // foreach artist: |
1608 | - ListItem.Standard { |
1609 | - height: units.gu(4) |
1610 | - // when pressed on this row, change to albums of artist |
1611 | - Row { |
1612 | - Label { |
1613 | - text: i18n.tr("Artist 1") |
1614 | - } |
1615 | - } |
1616 | - } |
1617 | - |
1618 | - // toolbar |
1619 | - tools: defaultToolbar |
1620 | - |
1621 | - Column { |
1622 | - anchors.centerIn: parent |
1623 | - anchors.fill: parent |
1624 | - } |
1625 | - } |
1626 | - } |
1627 | - |
1628 | - // Third tab begins here - albums here |
1629 | - Tab { |
1630 | - objectName: "Albums Tab" |
1631 | - |
1632 | - title: i18n.tr("Albums") |
1633 | - page: Page { |
1634 | - anchors.margins: units.gu(2) |
1635 | - |
1636 | - Column { |
1637 | - anchors.centerIn: parent |
1638 | - anchors.fill: parent |
1639 | - } |
1640 | - |
1641 | - // toolbar |
1642 | - tools: defaultToolbar |
1643 | - |
1644 | - Column { |
1645 | - anchors.centerIn: parent |
1646 | - } |
1647 | - } |
1648 | - } |
1649 | - |
1650 | - // Fourth tab - tracks in ~/Music |
1651 | - Tab { |
1652 | - objectName: "Tracks Tab" |
1653 | - |
1654 | - title: i18n.tr("Tracks") |
1655 | - page: MusicTracks { id: musicTracksPage } |
1656 | - } // 4th tab |
1657 | - |
1658 | - } // tabs |
1659 | + MusicTracks { id: musicTracksPage } |
1660 | + |
1661 | } // main view |
1662 | |
1663 | === added file 'playing-list.js' |
1664 | --- playing-list.js 1970-01-01 00:00:00 +0000 |
1665 | +++ playing-list.js 2013-06-05 04:48:28 +0000 |
1666 | @@ -0,0 +1,34 @@ |
1667 | +//playing-list.js |
1668 | +.pragma library |
1669 | +var myArray = new Array() |
1670 | +var myLocation = new Array() |
1671 | + |
1672 | +function getList() { |
1673 | + return myArray |
1674 | +} |
1675 | + |
1676 | +function at(index) { |
1677 | + return myLocation[index] |
1678 | +} |
1679 | + |
1680 | +function addItem(item, index) { |
1681 | + myArray.push(item) |
1682 | + myLocation.push(index) |
1683 | +} |
1684 | + |
1685 | +function contains(item) { |
1686 | + return myArray.indexOf(item) !== -1 |
1687 | +} |
1688 | + |
1689 | +function indexOf(item) { |
1690 | + return myArray.indexOf(item) |
1691 | +} |
1692 | + |
1693 | +function size() { |
1694 | + return myArray.length |
1695 | +} |
1696 | + |
1697 | +function clear() { |
1698 | + myArray = [] |
1699 | + myLocation = [] |
1700 | +} |
PASSED: Continuous integration, rev:25 91.189. 93.125: 8080/job/ music-app- ci/6/ 91.189. 93.125: 8080/job/ music-app- quantal- amd64-ci/ 6 91.189. 93.125: 8080/job/ music-app- raring- amd64-ci/ 6
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.125: 8080/job/ music-app- ci/6/rebuild
http://