diff --git a/orion.pro b/orion.pro index 260a02e..d099d99 100644 --- a/orion.pro +++ b/orion.pro @@ -29,11 +29,11 @@ SOURCES += src/main.cpp\ src/util/runguard.cpp \ src/customapp.cpp \ src/util/notificationmaker.cpp \ - src/network/vodoperation.cpp \ src/model/vod.cpp \ src/model/vodlistmodel.cpp \ src/model/vodmanager.cpp \ - src/network/vodsearchoperation.cpp + src/network/vodsearchoperation.cpp \ + src/network/vodstreamextractoperation.cpp HEADERS += src/model/channel.h \ @@ -52,12 +52,12 @@ HEADERS += src/model/channel.h \ src/util/runguard.h \ src/customapp.h \ src/util/notificationmaker.h \ - src/network/vodoperation.h \ src/model/vod.h \ src/model/vodlistmodel.h \ src/model/vodmanager.h \ src/network/vodsearchoperation.h \ - src/network/urls.h + src/network/urls.h \ + src/network/vodstreamextractoperation.h QMAKE_CXXFLAGS += -std=c++11 -Wall -O2 diff --git a/src/model/vodmanager.cpp b/src/model/vodmanager.cpp index 2673564..48d4bad 100644 --- a/src/model/vodmanager.cpp +++ b/src/model/vodmanager.cpp @@ -3,7 +3,7 @@ VodManager::VodManager() { vodSearch = new VodSearchOperation(); - vodGet = new VodOperation(); + vodGet = new VodStreamExtractOperation(); model = new VodListModel(); connect(vodSearch, SIGNAL(operationFinished()), this, SLOT(onSearchFinished())); @@ -49,7 +49,7 @@ VodListModel *VodManager::getModel() const return model; } -VodOperation *VodManager::getVodGet() const +VodStreamExtractOperation *VodManager::getVodGet() const { return vodGet; } diff --git a/src/model/vodmanager.h b/src/model/vodmanager.h index bc58583..f89e2e5 100644 --- a/src/model/vodmanager.h +++ b/src/model/vodmanager.h @@ -4,7 +4,7 @@ #include #include "vodlistmodel.h" #include "../network/vodsearchoperation.h" -#include "../network/vodoperation.h" +#include "../network/vodstreamextractoperation.h" class VodManager: public QObject { @@ -20,7 +20,7 @@ class VodManager: public QObject Q_INVOKABLE void getStreams(const QString vodId); - VodOperation *getVodGet() const; + VodStreamExtractOperation *getVodGet() const; Q_INVOKABLE QStringList getResults() const; @@ -39,7 +39,7 @@ public slots: QString game; VodListModel *model; VodSearchOperation *vodSearch; - VodOperation *vodGet; + VodStreamExtractOperation *vodGet; }; #endif // VODMANAGER_H diff --git a/src/network/vodsearchoperation.cpp b/src/network/vodsearchoperation.cpp index 06beb9c..7bff9f7 100644 --- a/src/network/vodsearchoperation.cpp +++ b/src/network/vodsearchoperation.cpp @@ -19,8 +19,13 @@ void VodSearchOperation::search(const QString channelName, quint32 offset, quint QString url = QString(KRAKEN_API) + QString("/channels/%1/videos").arg(channelName) + QString("?offset=%1").arg(offset) - + QString("&limit=%1").arg(limit) - + "&hls=true"; + + QString("&limit=%1").arg(limit); + + if (ONLY_BROADCASTS) + url += "&broadcasts=true"; + + if (USE_HLS) + url += "&hls=true"; QNetworkRequest request; request.setUrl(QUrl(url)); diff --git a/src/network/vodsearchoperation.h b/src/network/vodsearchoperation.h index ad1a70b..842d546 100644 --- a/src/network/vodsearchoperation.h +++ b/src/network/vodsearchoperation.h @@ -9,6 +9,9 @@ #include "../model/vod.h" #include "urls.h" +#define ONLY_BROADCASTS true +#define USE_HLS true + class VodSearchOperation: public QNetworkAccessManager { Q_OBJECT diff --git a/src/network/vodoperation.cpp b/src/network/vodstreamextractoperation.cpp similarity index 69% rename from src/network/vodoperation.cpp rename to src/network/vodstreamextractoperation.cpp index 5082b34..8c68434 100644 --- a/src/network/vodoperation.cpp +++ b/src/network/vodstreamextractoperation.cpp @@ -1,36 +1,36 @@ -#include "vodoperation.h" +#include "vodstreamextractoperation.h" #include "../util/jsonparser.h" #include "../util/m3u8parser.h" #include #include #include -VodOperation::VodOperation() +VodStreamExtractOperation::VodStreamExtractOperation() { connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleReply(QNetworkReply*))); } -VodOperation::~VodOperation() +VodStreamExtractOperation::~VodStreamExtractOperation() { result.clear(); } -QString VodOperation::getVod() const +QString VodStreamExtractOperation::getVod() const { return vod; } -void VodOperation::setVod(const QString &value) +void VodStreamExtractOperation::setVod(const QString &value) { vod = value; } -QStringList VodOperation::getResult() const +QStringList VodStreamExtractOperation::getResult() const { return result; } -void VodOperation::run(const QString vod_id) +void VodStreamExtractOperation::run(const QString vod_id) { vod = vod_id; @@ -40,7 +40,7 @@ void VodOperation::run(const QString vod_id) getExtractionData(); } -void VodOperation::getExtractionData() +void VodStreamExtractOperation::getExtractionData() { phase = 0; @@ -53,7 +53,7 @@ void VodOperation::getExtractionData() get(request); } -void VodOperation::getM3U(QString url) +void VodStreamExtractOperation::getM3U(QString url) { phase = 1; @@ -67,7 +67,7 @@ void VodOperation::getM3U(QString url) get(request); } -void VodOperation::handleReply(QNetworkReply* reply) +void VodStreamExtractOperation::handleReply(QNetworkReply* reply) { if (reply->error() != QNetworkReply::NoError){ qDebug() << reply->errorString(); diff --git a/src/network/vodoperation.h b/src/network/vodstreamextractoperation.h similarity index 69% rename from src/network/vodoperation.h rename to src/network/vodstreamextractoperation.h index 16a3bc7..4a51ae0 100644 --- a/src/network/vodoperation.h +++ b/src/network/vodstreamextractoperation.h @@ -1,5 +1,5 @@ -#ifndef VODOPERATION_H -#define VODOPERATION_H +#ifndef VODSTREAMEXTRACTOPERATION_H +#define VODSTREAMEXTRACTOPERATION_H #include #include @@ -7,7 +7,7 @@ //Fetches the network streams data for player -class VodOperation: public QNetworkAccessManager +class VodStreamExtractOperation: public QNetworkAccessManager { Q_OBJECT @@ -15,8 +15,8 @@ class VodOperation: public QNetworkAccessManager void getM3U(QString url); public: - VodOperation(); - ~VodOperation(); + VodStreamExtractOperation(); + ~VodStreamExtractOperation(); Q_INVOKABLE void run(const QString vod_id); @@ -37,4 +37,4 @@ public slots: quint8 phase; }; -#endif // VODOPERATION_H +#endif // VODSTREAMEXTRACTOPERATION_H diff --git a/src/qml/FavouritesView.qml b/src/qml/FavouritesView.qml index 893c4c8..d1bba7d 100644 --- a/src/qml/FavouritesView.qml +++ b/src/qml/FavouritesView.qml @@ -38,7 +38,7 @@ Item{ onItemClicked: { if (currentItem.online){ - player.play(currentItem) + player.getStreams(currentItem) } } @@ -54,20 +54,20 @@ Item{ text: "Watch;play" onTriggered: { if (_menu.item.online){ - player.play(_menu.item) + player.getStreams(_menu.item) } } } MenuItem { - text: "Remove;remove" + text: "Videos;video" onTriggered: { - g_cman.removeFromFavourites(_menu.item._id) + vods.search(_menu.item) } } MenuItem { - text: "Videos;video" + text: "Remove;remove" onTriggered: { - vods.search(_menu.item) + g_cman.removeFromFavourites(_menu.item._id) } } } diff --git a/src/qml/FeaturedView.qml b/src/qml/FeaturedView.qml index 187dbbd..b236196 100644 --- a/src/qml/FeaturedView.qml +++ b/src/qml/FeaturedView.qml @@ -49,14 +49,14 @@ Item { onItemClicked: { if (currentItem.online){ - player.play(currentItem) + player.getStreams(currentItem) } } onItemRightClicked: { _menu.item = currentItem _menu.items[0].enabled = _menu.item.online - var item = _menu.items[1] + var item = _menu.items[2] item.text = !_menu.item.favourite ? "Add favourite;fav" : "Remove favourite;remove" _menu.state = !_menu.item.favourite ? 1 : 2 @@ -78,24 +78,26 @@ Item { text: "Watch;play" onTriggered: { if (_menu.item.online){ - player.play(_menu.item) + player.getStreams(_menu.item) } } } MenuItem { - id: _fav + text: "Videos;video" onTriggered: { - _menu.addRemoveFavourite() + vods.search(_menu.item) } } MenuItem { - text: "Videos;video" + id: _fav onTriggered: { - vods.search(_menu.item) + _menu.addRemoveFavourite() } } + + } Timer { diff --git a/src/qml/PlayerView.qml b/src/qml/PlayerView.qml index 2db4ab2..b065b57 100644 --- a/src/qml/PlayerView.qml +++ b/src/qml/PlayerView.qml @@ -23,7 +23,17 @@ Item { id: root - function play(channel, vod){ + function loadAndPlay(){ + setWatchingTitle() + + renderer.command(["loadfile", qualityMap[quality]]) + + spinner.visible = false + + renderer.play() + } + + function getStreams(channel, vod){ if (!channel){ return @@ -49,7 +59,6 @@ Item { } paused = false - //renderer.play() currentChannel = { "_id": channel._id, @@ -113,21 +122,17 @@ Item { sourcesBox.entries = qualityMap if (qualityMap[quality]){ - setWatchingTitle() - - renderer.command(["loadfile", qualityMap[quality]]) - - spinner.visible = false - sourcesBox.setIndex(quality) - } - renderer.play() + loadAndPlay() + } } - function seekTo(percentage) { + function seekTo(fraction) { + console.log(fraction) if (isVod){ - var pos = duration / 100 * percentage + var pos = Math.floor(duration * fraction) + console.log(pos) renderer.setProperty("playback-time", pos) } } @@ -284,10 +289,14 @@ Item { } } - Item { - + SeekBar { + id: seekBar visible: isVod + onUserChangedPosition: { + seekTo(position) + } + anchors { top: parent.top bottom: parent.bottom @@ -295,57 +304,14 @@ Item { right: vol.left } - Rectangle { - id: seekBar - color: Styles.seekBar - - anchors { - left: parent.left - right: parent.right - leftMargin: dp(10) - rightMargin: dp(10) - - verticalCenter: parent.verticalCenter - } - - height: dp(6) - - Rectangle { - color: "white" - id: fillBar - anchors { - left: parent.left - top: parent.top - bottom: parent.bottom - } - - Connections { - target: renderer - onPositionChanged: { - var width = Math.max(0,Math.min(position / duration * seekBar.width, seekBar.width)) - - fillBar.width = width - } - } - } - } - - MouseArea { - anchors { - fill: parent - topMargin: dp(10) - bottomMargin: dp(10) - } - - propagateComposedEvents: false - onClicked: { - var percentage = Math.max(0, Math.min(mouseX / seekBar.width * 100, 100)) - seekTo(percentage) + Connections { + target: renderer + onPositionChanged: { + seekBar.setPosition(position / duration, duration) } } } - VolumeSlider { id: vol z: parent.z + 1 @@ -375,7 +341,7 @@ Item { onIndexChanged: { if (index != quality){ quality = index - play(currentChannel) + loadAndPlay() } } } diff --git a/src/qml/SearchView.qml b/src/qml/SearchView.qml index a05e7ba..b9a267c 100644 --- a/src/qml/SearchView.qml +++ b/src/qml/SearchView.qml @@ -199,7 +199,7 @@ Item { onItemClicked: { if (currentItem.online){ - player.play(currentItem) + player.getStreams(currentItem) } } @@ -208,7 +208,7 @@ Item { _menu.items[0].enabled = _menu.item.online - var item = _menu.items[1] + var item = _menu.items[2] item.text = !_menu.item.favourite ? "Add favourite;fav" : "Remove favourite;remove" _menu.state = !_menu.item.favourite ? 1 : 2 @@ -230,22 +230,22 @@ Item { text: "Watch;play" onTriggered: { if (_menu.item.online){ - player.play(_menu.item) + player.getStreams(_menu.item) } } } MenuItem { - id: _fav + text: "Videos;video" onTriggered: { - _menu.addRemoveFavourite() + vods.search(_menu.item) } } MenuItem { - text: "Videos;video" + id: _fav onTriggered: { - vods.search(_menu.item) + _menu.addRemoveFavourite() } } } diff --git a/src/qml/VodsView.qml b/src/qml/VodsView.qml index df9b0be..c4d204d 100644 --- a/src/qml/VodsView.qml +++ b/src/qml/VodsView.qml @@ -10,9 +10,9 @@ Item{ function search(channel){ selectedChannel = channel; - g_vodmgr.search(selectedChannel.name, 0, 50) + g_vodmgr.search(selectedChannel.name, 0, 25) - itemCount = 50 + itemCount = 25 requestSelectionChange(4) } @@ -54,7 +54,7 @@ Item{ } onItemClicked: { - player.play(selectedChannel, selectedItem) + player.getStreams(selectedChannel, selectedItem) } onItemRightClicked: { @@ -67,7 +67,7 @@ Item{ MenuItem { text: "Watch;play" onTriggered: { - player.play(selectedChannel, _menu.item) + player.getStreams(selectedChannel, _menu.item) } } } diff --git a/src/qml/components/SeekBar.qml b/src/qml/components/SeekBar.qml new file mode 100644 index 0000000..4e4b7cb --- /dev/null +++ b/src/qml/components/SeekBar.qml @@ -0,0 +1,114 @@ +import QtQuick 2.0 + +import "../styles.js" as Styles + +Item { + property int duration + property int position + + id: root + + signal userChangedPosition(real position) + + function setPosition(fraction, duration){ + if (root.duration !== duration) + root.duration = duration + root.position = Math.floor(duration * fraction) + fillBar.width = Math.floor(fraction * seekBar.width) + + time.updateTime() + } + + onDurationChanged: { + time.duration = time.getTime(duration) + } + + Rectangle { + id: seekBar + color: Styles.seekBar + + anchors { + left: parent.left + right: parent.right + leftMargin: dp(10) + rightMargin: dp(10) + + verticalCenter: parent.verticalCenter + } + + height: dp(6) + + Rectangle { + color: "white" + id: fillBar + + width: 0 + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + } + } + } + + MouseArea { + anchors { + top: parent.top + bottom: parent.bottom + left: seekBar.left + right: seekBar.right + topMargin: dp(10) + bottomMargin: dp(10) + } + + propagateComposedEvents: false + onClicked: { + userChangedPosition(mouseX / seekBar.width) + } + } + + Item { + + property string duration + + id: time + anchors { + top: parent.top + topMargin: dp(6) + horizontalCenter: parent.horizontalCenter + } + + height: _time.contentHeight + width: _time.contentWidth + + function updateTime() { + _time.text = getTime(root.position) + "/" + duration + } + + function getTime(totalSec){ + var hours = parseInt(totalSec / 3600) % 24; + var minutes = parseInt(totalSec / 60) % 60; + var seconds = totalSec % 60; + + var result = ""; + + if (hours > 0) + result += hours + ":"; + result += (minutes < 10 ? "0" + minutes : minutes) + ":"; + result += (seconds < 10 ? "0" + seconds : seconds); + + return result + } + + Text { + id: _time + text: "hh:mm:ss / hh:mm:ss" + color: Styles.iconColor + font.bold: true + font.family: "Droid Sans" + font.pointSize: dp(12) + wrapMode: Text.WordWrap + renderType: Text.NativeRendering + } + } +} diff --git a/src/qml/qml.qrc b/src/qml/qml.qrc index 6f5da9e..9560c26 100644 --- a/src/qml/qml.qrc +++ b/src/qml/qml.qrc @@ -38,5 +38,6 @@ style/qmldir VodsView.qml components/Video.qml + components/SeekBar.qml