~nik90/podbird/devel-branch-sync-4

« back to all changes in this revision

Viewing changes to app/podbird.qml

  • Committer: Michael Sheldon
  • Author(s): Nekhelesh Ramananthan
  • Date: 2016-03-28 23:19:36 UTC
  • mfrom: (149.2.8 devel-branch-sync-2)
  • Revision ID: michael.sheldon@canonical.com-20160328231936-g9fydaeiwkx7vgk3
Add queue support. Use DownloadManager to handle download queues and unfinished downloads when app is closed. Switch to new GridView. Add multi-select for Episodes tab.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import QtQuick 2.4
20
20
import Podbird 1.0
21
 
import UserMetrics 0.1
22
 
import QtMultimedia 5.4
 
21
import QtMultimedia 5.6
23
22
import Ubuntu.Connectivity 1.0
24
23
import Qt.labs.settings 1.0
25
24
import Ubuntu.Components 1.3
26
25
import QtQuick.LocalStorage 2.0
27
 
import Ubuntu.DownloadManager 0.1
 
26
import Ubuntu.DownloadManager 1.2
28
27
import "ui"
29
28
import "themes" as Themes
30
29
import "podcasts.js" as Podcasts
45
44
 
46
45
    Component.onDestruction: {
47
46
        console.log("[LOG]: Download cancelled");
48
 
        downloader.cancel();
49
47
        var db = Podcasts.init()
50
48
        db.transaction(function (tx) {
51
49
            tx.executeSql('UPDATE Episode SET queued=0 WHERE queued=1');
52
50
        })
 
51
        Podcasts.clearQueue()
53
52
    }
54
53
 
55
54
    // RefreshModel function to call refreshModel() function of the tab currently
138
137
        }
139
138
    }
140
139
 
141
 
    SingleDownload {
 
140
    Component {
 
141
        id: singleDownloadComponent
 
142
        SingleDownload {
 
143
            id: singleDownloadObject
 
144
            property string image
 
145
            property string title
 
146
            property string guid
 
147
            metadata: Metadata {
 
148
                showInIndicator: true
 
149
                title: singleDownloadObject.title
 
150
            }
 
151
        }
 
152
    }
 
153
 
 
154
    function downloadEpisode(image, title, guid, url) {
 
155
        var singleDownload = singleDownloadComponent.createObject(podbird, {"image": image, "title": title, "guid": guid})
 
156
        singleDownload.download(url)
 
157
    }
 
158
 
 
159
    DownloadManager {
142
160
        id: downloader
143
 
        property var queue: []
144
 
        property string downloadingGuid
145
 
 
146
 
        onFinished: {
 
161
 
 
162
        property string downloadingGuid: downloads.length > 0 ? downloads[0].guid : "NULL"
 
163
        property int progress: downloads.length > 0 ? downloads[0].progress : 0
 
164
 
 
165
        cleanDownloads: true
 
166
        onDownloadFinished: {
147
167
            var db = Podcasts.init();
148
168
            var finalLocation = fileManager.saveDownload(path);
149
169
            db.transaction(function (tx) {
150
 
                tx.executeSql("UPDATE Episode SET downloadedfile=?, queued=0 WHERE guid=?", [finalLocation, downloadingGuid]);
151
 
                queue.shift();
152
 
                if (queue.length > 0) {
153
 
                    downloadingGuid = queue[0][0];
154
 
                    download(queue[0][1]);
155
 
                } else {
156
 
                    downloadingGuid = "";
157
 
                }
 
170
                tx.executeSql("UPDATE Episode SET downloadedfile=?, queued=0 WHERE guid=?", [finalLocation, download.guid]);
158
171
            });
159
172
        }
160
173
 
161
 
        function addDownload(guid, url) {
162
 
            queue.push([guid, url]);
163
 
            if (queue.length == 1) {
164
 
                downloadingGuid = guid;
165
 
                download(url);
166
 
            }
167
 
        }
168
 
    }
169
 
 
170
 
    // UserMetrics to show Podbird stats on welcome screen
171
 
    Metric {
172
 
        id: podcastsMetric
173
 
        name: "podcast-metrics"
174
 
        // 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)
175
 
        format: i18n.tr("Podcasts listened to today: <b>%1</b>")
176
 
        emptyFormat: i18n.tr("No podcasts listened to today")
177
 
        domain: "com.mikeasoft.podbird"
178
 
    }
179
 
 
180
 
    // Load the media player only when the user starts to play some media. This
181
 
    // should improve app-startup slightly.
182
 
    Loader {
183
 
        id: playerLoader
184
 
        sourceComponent: currentUrl != "" ? playerComponent : undefined
185
 
    }
186
 
 
187
 
    Component {
188
 
        id: playerComponent
189
 
        MediaPlayer {
190
 
            id: player
191
 
 
192
 
            property bool podcastCounted: false
193
 
 
194
 
            source: currentUrl
195
 
 
196
 
            onSourceChanged: {
197
 
                podcastCounted = false
198
 
            }
199
 
 
200
 
            onPositionChanged: {
201
 
                if (currentGuid == "" || duration <= 0) {
202
 
                    return;
203
 
                }
204
 
 
205
 
                if (position > 10000 && !podcastCounted) {
206
 
                    podcastCounted = true
207
 
                    podcastsMetric.increment()
208
 
                    console.log("[LOG]: Podcast User metric incremented")
209
 
                }
210
 
 
211
 
                var db = Podcasts.init();
212
 
                db.transaction(function (tx) {
213
 
                    tx.executeSql("UPDATE Episode SET position=? WHERE guid=?", [position >= duration ? 120 : position, currentGuid]);
214
 
                    if (position >= duration - 120) {
215
 
                        tx.executeSql("UPDATE Episode SET listened = 1 WHERE guid=?", [currentGuid]);
216
 
                    }
217
 
                });
218
 
            }
 
174
        onErrorFound: {
 
175
            console.log("[ERROR]: " + download.errorMessage)
 
176
        }
 
177
    }
 
178
 
 
179
    MediaPlayer {
 
180
        id: player
 
181
 
 
182
        // Wrapper function around decodeURIComponent() to prevent exceptions
 
183
        // from bubbling up to the app.
 
184
        function decodeFileURI(filename)
 
185
        {
 
186
            var newFilename = "";
 
187
            try {
 
188
                newFilename = decodeURIComponent(filename);
 
189
            } catch (e) {
 
190
                newFilename = filename;
 
191
                console.log("Unicode decoding error:", filename, e.message)
 
192
            }
 
193
 
 
194
            return newFilename;
 
195
        }
 
196
 
 
197
        function metaForSource(source) {
 
198
            var blankMeta = {
 
199
                name: "",
 
200
                artist: "",
 
201
                image: "",
 
202
                guid: "",
 
203
            }
 
204
 
 
205
            source = source.toString()
 
206
 
 
207
            return Podcasts.lookup(decodeFileURI(source)) || blankMeta;
 
208
        }
 
209
 
 
210
        function toggle() {
 
211
            if (playbackState === MediaPlayer.PlayingState) {
 
212
                pause()
 
213
            } else {
 
214
                play()
 
215
            }
 
216
        }
 
217
 
 
218
        function playEpisode(guid, image, name, artist, url) {
 
219
            // Clear current queue
 
220
            player.playlist.clear()
 
221
            Podcasts.clearQueue()
 
222
 
 
223
            // Add episode to queue
 
224
            Podcasts.addItemToQueue(guid, image, name, artist, url)
 
225
            player.playlist.addItem(url)
 
226
 
 
227
            // Play episode
 
228
            player.play()
 
229
        }
 
230
 
 
231
        function addEpisodeToQueue(guid, image, name, artist, url) {
 
232
            Podcasts.addItemToQueue(guid, image, name, artist, url)
 
233
            player.playlist.addItem(url)
 
234
 
 
235
            // If added episode is the first one in the queue, then set the current metadata
 
236
            // so that the bottom player controls will be shown, allowing the user to play
 
237
            // the episode if he chooses to.
 
238
            if (player.playlist.itemCount === 0) {
 
239
                currentGuid = guid
 
240
                currentName = name
 
241
                currentArtist = artist
 
242
                currentImage = image
 
243
                currentUrl = url
 
244
            }
 
245
        }
 
246
 
 
247
        property bool endOfMedia: false
 
248
        property double progress: 0
 
249
 
 
250
        playlist: Playlist {
 
251
            playbackMode: Playlist.Sequential
 
252
 
 
253
            readonly property bool canGoPrevious: currentIndex !== 0
 
254
            readonly property bool canGoNext: currentIndex !== itemCount - 1
 
255
 
 
256
            onCurrentItemSourceChanged: {
 
257
                var meta = player.metaForSource(currentItemSource)
 
258
                currentGuid = "";
 
259
                currentName = meta.name
 
260
                currentArtist = meta.artist
 
261
                currentImage = meta.image
 
262
                currentGuid = meta.guid
 
263
            }
 
264
        }
 
265
 
 
266
        onStatusChanged: {
 
267
            if (status === MediaPlayer.EndOfMedia) {
 
268
                console.log("[LOG]: End of Media. Stopping.")
 
269
                endOfMedia = true
 
270
                stop()
 
271
            }
 
272
        }
 
273
 
 
274
        onStopped: {
 
275
            if (playlist.itemCount > 0) {
 
276
                if (endOfMedia) {
 
277
                    // We just ended media, so jump to start of playlist
 
278
                    playlist.currentIndex  = 0;
 
279
 
 
280
                    // Play then pause otherwise when we come from EndOfMedia
 
281
                    // it calls next() until EndOfMedia again.
 
282
                    play()
 
283
                }
 
284
 
 
285
                pause()
 
286
            }
 
287
 
 
288
            // Always reset endOfMedia
 
289
            endOfMedia = false
219
290
        }
220
291
    }
221
292
 
290
361
        states: [
291
362
            State {
292
363
                name: "shown"
293
 
                when: currentUrl != "" && !mainStack.currentPage.isNowPlayingPage
 
364
                when: player.playlist.itemCount !== 0 && !mainStack.currentPage.isNowPlayingPage
294
365
                PropertyChanges { target: playerControlLoader; anchors.bottomMargin: 0 }
295
366
            },
296
367
 
297
368
            State {
298
369
                name: "hidden"
299
 
                when: currentUrl == "" || mainStack.currentPage.isNowPlayingPage || !playerControl.visible
 
370
                when: player.playlist.itemCount === 0 || mainStack.currentPage.isNowPlayingPage || !playerControl.visible
300
371
                PropertyChanges { target: playerControlLoader; anchors.bottomMargin: -units.gu(7) }
301
372
            }
302
373
        ]