forked from nesnomis/harbour-allradio2
Initial commit (new git name)
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
BackgroundItem {
|
||||
property string headerText: ""
|
||||
height: label.height + (Theme.paddingLarge * 2)
|
||||
Label {
|
||||
id: label
|
||||
|
||||
width: parent.width - image.width
|
||||
//height: Theme.itemSizeLarge
|
||||
text: headerText
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.bold: true
|
||||
//verticalAlignment: Text.AlignVCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.paddingLarge
|
||||
anchors.right: image.left
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
color: Theme.primaryColor
|
||||
// visible: radioBrowser.getCountryName(_country) || playedCountries.count > 0 ? true : false
|
||||
}
|
||||
Image {
|
||||
id: image
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
anchors.verticalCenter: label.verticalCenter
|
||||
source: "image://theme/icon-m-right"
|
||||
}
|
||||
Rectangle {
|
||||
//visible: fill
|
||||
anchors.fill: parent
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: Theme.rgba(Theme.highlightBackgroundColor,0.125) }
|
||||
GradientStop { position: 1.0; color: "transparent" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
import "../delegates"
|
||||
//import "../delegates_"
|
||||
import "../items"
|
||||
|
||||
DockedPanel {
|
||||
// property real showP: 0.0
|
||||
// property int tab: 0
|
||||
id: dock
|
||||
|
||||
// property alias videoSource: videoPlayer.videoSource
|
||||
|
||||
dock: Dock.Bottom
|
||||
z: 99
|
||||
width: parent.width
|
||||
height: Theme.itemSizeExtraLarge //play.height + (Theme.paddingMedium * 2)
|
||||
animationDuration: 250
|
||||
open: !radioBrowser.loading ? true : false
|
||||
|
||||
// onOpenChanged: if (open) {
|
||||
// mediaPlayerPanel.videoSource = radioPlayer
|
||||
// if (radioPlayer.isPlaying || radioPlayer.isPaused && radioPlayer.radioVideo) radioPlayer.resumeStream()
|
||||
// }
|
||||
|
||||
// onVisibleChanged: if (visible) {
|
||||
// mediaPlayerPanel.videoSource = radioPlayer
|
||||
// if (radioPlayer.isPlaying || radioPlayer.isPaused && radioPlayer.radioVideo) radioPlayer.resumeStream()
|
||||
// }
|
||||
|
||||
// onOpenChanged: open ? videoOn() : videoOff()
|
||||
|
||||
|
||||
SilicaItem {
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: Theme.itemSizeExtraLarge
|
||||
/* VideoPlayer {
|
||||
id: videoPlayer
|
||||
z:98
|
||||
//anchors.top: orientation === Orientation.Portrait ? stationimage.top : allRadio.top
|
||||
//anchors.bottom: orientation === Orientation.Portrait ? stationimage.bottom : allRadio.bottom
|
||||
//anchors.left: orientation === Orientation.Portrait ? stationimage.left : allRadio.left
|
||||
//anchors.right: orientation === Orientation.Portrait ? stationimage.right : allRadio.right
|
||||
//anchors.margins: orientation === Orientation.Portrait ? stationimage.border.width : 0
|
||||
anchors.fill: stationimage
|
||||
visible: radioPlayer.isVideo && !radioPlayer.isPaused ? true : false
|
||||
onVisibleChanged: visible ? enabled=true : enabled = false
|
||||
// videoSource: radioPlayer//dock.open ? radioPlayer : null
|
||||
//color: orientation === Orientation.Portrait ? "transparent" : "black"
|
||||
//videoSource: radioPlayer.videoP ? null : radioPlayer
|
||||
//videoSource: radioPlayer.playerPageOpen ? null : radioPlayer
|
||||
} */
|
||||
RadioImage {
|
||||
id: stationimage
|
||||
// visible: !videoPlayer.visible
|
||||
height: parent.height * 0.8 //- (Theme.paddingMedium * 2)
|
||||
width: height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.paddingMedium
|
||||
stationImage: radioPlayer._favicon
|
||||
stationLabel: radioPlayer._name
|
||||
}
|
||||
|
||||
Item {
|
||||
id: songInfo
|
||||
anchors.verticalCenter: stationimage.verticalCenter
|
||||
height: play.height //- (Theme.paddingMedium * 2)
|
||||
anchors.leftMargin: Theme.paddingLarge
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
anchors.left: stationimage.right
|
||||
anchors.right: play.left
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width
|
||||
Label {
|
||||
id: rname
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
elide: Text.ElideRight
|
||||
width: parent.width
|
||||
font.bold: true
|
||||
text: radioPlayer._name
|
||||
}
|
||||
// Row {
|
||||
// spacing: Theme.paddingMedium
|
||||
/* Image {
|
||||
id: headerLogo
|
||||
anchors.bottom: rcountry.bottom
|
||||
height: rcountry.height * 0.8
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
// source: radioPlayer._cc === "" ? radioPlayer._cc ? "../images/bycountry_t.png" : "" : "../flags/"+radioPlayer._cc.toLowerCase()+".png"
|
||||
source: "../flags/"+radioPlayer._cc.toLowerCase()+".png"
|
||||
} */
|
||||
Label {
|
||||
id: rcountry
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: radioPlayer.radioCountryName
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: songInfo.right
|
||||
onClicked: {
|
||||
// if (radioPlayer.isPlaying && radioPlayer.radioVideo)
|
||||
//if (radioPlayer.radioVideo) radioPlayer.videoPause()
|
||||
pageStack.push("../pages/RadioPlayerPage.qml")
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: play
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.paddingMedium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon.source: radioPlayer.isPlaying ? "image://theme/icon-l-pause" : "image://theme/icon-l-play"
|
||||
onClicked: if (radioPlayer.isPlaying) radioPlayer.pauseStream(); else {radioPlayer.resumeStream(); }//if (radioPlayer.radioVideo) pageStack.push("RadioPlayerPage.qml")}//icon.source == "image://theme/icon-l-play" ? icon.source = "image://theme/icon-l-pause" : icon.source = "image://theme/icon-l-play"
|
||||
}
|
||||
BusyIndicator {
|
||||
id: busy
|
||||
visible: running
|
||||
anchors.centerIn: play
|
||||
size: BusyIndicatorSize.Medium
|
||||
running: radioPlayer.radioStatus===2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
// This is my "quick and dirty" solution to fix the initial stuttering when playing a radio station.
|
||||
// It is not pretty but it works, until there is a better solution (or fix in MediaPlayer.
|
||||
|
||||
Timer {
|
||||
interval: 100; running: false; repeat: false
|
||||
onTriggered: playStreamTimer()
|
||||
|
||||
function playStreamTimer() {
|
||||
source = ""
|
||||
source = _url_resolved
|
||||
isPlaying = true
|
||||
isPaused = false
|
||||
play()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
// properties:
|
||||
// -----------
|
||||
// server - selected server name)
|
||||
// serverUrl - Url of the selected server
|
||||
// stations - Number of stations in selected server
|
||||
// tags - Number of tags in selected server
|
||||
// countries - Number of countries in selected server
|
||||
// count - Number of servers in model
|
||||
// model - Model containing list of servers (if you want to manually choose server)
|
||||
// --------------------------------------------------------------------------------
|
||||
// functions:
|
||||
// ----------
|
||||
// getList - Refresh the ListModel and add a random url to server
|
||||
// getRandom - Get a random url from the ListModel and add url to server
|
||||
// ---------------------------------------------------------------------
|
||||
import QtQuick 2.0
|
||||
import "../models"
|
||||
|
||||
Item {
|
||||
property string _useragent: "AllRadio/2.0.0 (test) (SailfishOS; Linux) nesnomis@gmail.com"
|
||||
property int _tags: 0
|
||||
property int _countries: 0
|
||||
property int _c: 0
|
||||
|
||||
// Properties to be used in application -------------------------------------------------
|
||||
property ListModel serversModel : ListModel { id: serversModel }
|
||||
property ListModel serverStatsModel : ListModel { id: serverStatsModel }
|
||||
property ListModel votedModel : ListModel {id: votedModel}
|
||||
property CountryListModel countriesModel : CountryListModel {id:countriesModel}
|
||||
//property TagListModel tagsModel : TagListModel {id:tagsModel}
|
||||
property string serverUrl: ""
|
||||
property string server: ""
|
||||
property bool online: false
|
||||
property bool voted: false
|
||||
property int stationCount: 0
|
||||
property int tagCount: 0
|
||||
//property int viewTagCount: tagsModel.maxCount
|
||||
property int countryCount: 0
|
||||
property bool loading: stationCount !== 0 && tagCount !== 0 && countryCount !== 0 ? false : true
|
||||
property int serverIndex: 0
|
||||
property int connectIndex: -1
|
||||
property string lookup: sModel.get(serverIndex).url //"http://fi2.api.radio-browser.info/json/servers"
|
||||
// ---------------------------------------------------------------------------------------
|
||||
Timer {
|
||||
id: sTimer
|
||||
interval: 2000; running: false; repeat: false
|
||||
onTriggered: {
|
||||
if (serverIndex < sModel.count-1) serverIndex = serverIndex + 1; else serverIndex = 0
|
||||
getList()
|
||||
}
|
||||
}
|
||||
//onServerIndexChanged: console.log(" ******* LOOKUP ******** ")+serverIndex
|
||||
|
||||
ListModel {
|
||||
id: sModel
|
||||
|
||||
ListElement {
|
||||
name: "all.api.radio-browser.info"
|
||||
url: "http://all.api.radio-browser.info/json/servers"
|
||||
}
|
||||
ListElement {
|
||||
name: "de1.api.radio-browser.info"
|
||||
url: "http://de1.api.radio-browser.info/json/servers"
|
||||
}
|
||||
ListElement {
|
||||
name: "de2.api.radio-browser.info"
|
||||
url: "http://de2.api.radio-browser.info/json/servers"
|
||||
}
|
||||
ListElement {
|
||||
name: "fi1.api.radio-browser.info"
|
||||
url: "http://fi1.api.radio-browser.info/json/servers"
|
||||
}
|
||||
ListElement {
|
||||
name: "fi3.api.radio-browser.info"
|
||||
url: "http://fi3.api.radio-browser.info/json/servers"
|
||||
}
|
||||
}
|
||||
|
||||
onOnlineChanged: {
|
||||
if (online && serverUrl !== "") {
|
||||
countriesModel.source = serverUrl + "/xml/countrycodes?hidebroken=true"
|
||||
}
|
||||
}
|
||||
// Not used?!?!?
|
||||
/* function getServer(s,u) {
|
||||
stationCount = 0
|
||||
tagCount = 0
|
||||
countryCount = 0
|
||||
server = s
|
||||
serverUrl = u
|
||||
getStats()
|
||||
} */
|
||||
|
||||
function connectServer(index) {
|
||||
if (serversModel.count > 0) {
|
||||
|
||||
server = serversModel.get(index).server
|
||||
if (serverUrl.length > 7 && url !== serverUrl) {loading=true;serverIndex = index;sTimer.running=false;getStats();} else {loading=true;serverIndex = index;getRandom();}
|
||||
}
|
||||
}
|
||||
// Choose a random server from available servers
|
||||
function getRandom(url) {
|
||||
if (serversModel.count > 0) {
|
||||
var random = Math.floor((Math.random() * serversModel.count) + 1) - 1
|
||||
serverUrl = serversModel.get(random).serverUrl
|
||||
server = serversModel.get(random).server
|
||||
if (serverUrl.length > 7 && url !== serverUrl) {sTimer.running=false;getStats();serverIndex=random} else getRandom();
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of available Radio Community Servers.
|
||||
function getList() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === 4 && req.status < 300) {
|
||||
|
||||
var obj = JSON.parse(req.responseText)
|
||||
serversModel.clear()
|
||||
for (var key in obj) {
|
||||
addIfNotExist(obj[key])
|
||||
}
|
||||
sTimer.running = false
|
||||
//console.log(" *** lookup *** "+serverIndex+": "+lookup)
|
||||
getRandom(lookup)
|
||||
} else if (req.readyState === 4 && req.status > 299) {
|
||||
if (serverIndex < sModel.count-1) serverIndex=serverIndex+1; else serverIndex=0;
|
||||
lookup=sModel.get(serverIndex).url
|
||||
//console.log(" *** lookup *** "+serverIndex+": "+lookup)
|
||||
getList();
|
||||
}
|
||||
};
|
||||
sTimer.running = true
|
||||
//console.log(" *** START : "+lookup)
|
||||
req.open("get", lookup);
|
||||
req.setRequestHeader('User-Agent',_useragent);
|
||||
req.send();
|
||||
}
|
||||
// Add available server to listmodel
|
||||
function addIfNotExist(server) {
|
||||
for (var i = 0; i < serversModel.count; i++) {
|
||||
if (serversModel.get(i).server === server.name) {
|
||||
return
|
||||
}
|
||||
}
|
||||
serversModel.append({"serverUrl": "http://"+server.name,"server": server.name})
|
||||
}
|
||||
// ----------------------------------------------
|
||||
// Station online?
|
||||
function getStats() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === 4 && req.status < 300) {
|
||||
var obj = req.response.split("{").pop();
|
||||
obj = JSON.parse("{"+obj)
|
||||
if (obj.status === "OK") {
|
||||
stationCount = obj.stations-obj.stations_broken
|
||||
tagCount = obj.tags
|
||||
if (obj.status === "OK") {online = true} else {online = false}
|
||||
}
|
||||
}
|
||||
};
|
||||
req.open("get", serverUrl+"/json/stats");
|
||||
req.setRequestHeader('User-Agent',_useragent);
|
||||
req.send();
|
||||
}
|
||||
// ----------------------------------------------
|
||||
// Vote/like for radio station on community radio browser.
|
||||
function upVote(stationuuid,returnValue) {
|
||||
var req = new XMLHttpRequest();
|
||||
var ret = false
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === 4 && req.status === 200) {
|
||||
var obj = req.response.split("{").pop();
|
||||
obj = JSON.parse("{"+obj)
|
||||
if (obj.ok) {
|
||||
if (obj.ok) {returnValue=true;console.log(" ****** VOTED *****")} else {returnValue=false;console.log(" ****** NOT VOTED *****")}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
};
|
||||
req.open("get", serverUrl+"/json/vote/"+stationuuid);
|
||||
req.setRequestHeader('User-Agent',_useragent);
|
||||
req.send();
|
||||
}
|
||||
// ----------------------------------------------
|
||||
// Load model with country names.
|
||||
CountryNameModel {id: countryNameModel}
|
||||
|
||||
function getCountryName(land) { // Get translated countryname
|
||||
for(var i = 0; i < countryNameModel.count; i++) {
|
||||
var current = countryNameModel.get(i);
|
||||
if(land === current.code) {
|
||||
return countryNameModel.countryname(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import QtQuick 2.0
|
||||
import QtMultimedia 5.6
|
||||
import Amber.Mpris 1.0
|
||||
|
||||
MprisPlayer {
|
||||
id: mprisPlayer
|
||||
property string song: ""
|
||||
property string artist: "AllRadio"
|
||||
|
||||
serviceName: "harbour-allradio"
|
||||
|
||||
identity: "AllRadio2"
|
||||
supportedUriSchemes: ["file"]
|
||||
supportedMimeTypes: ["audio/x-wav", "audio/x-vorbis+ogg", "audio/mpeg", "audio/mp4a-latm", "audio/x-aiff", "audio/flac"]
|
||||
|
||||
canControl: true
|
||||
canGoNext: radioPlayer.playlistIndex < radioPlayer.playlist.count -1 && radioPlayer._favorite
|
||||
canGoPrevious: radioPlayer.playlistIndex > 0 && radioPlayer._favorite
|
||||
canPause: radioPlayer.isPlaying ? true : false
|
||||
canPlay: radioPlayer.isPaused ? true : false
|
||||
canSeek: false
|
||||
hasTrackList: false
|
||||
loopStatus: Mpris.LoopNone
|
||||
shuffle: false
|
||||
volume: 1
|
||||
|
||||
playbackStatus: {
|
||||
if (radioPlayer.isPlaying) Mpris.Playing;
|
||||
else if (radioPlayer.isPaused) Mpris.Paused;
|
||||
else Mpris.Stopped;
|
||||
}
|
||||
|
||||
metaData {
|
||||
url: radioPlayer.source
|
||||
contributingArtist: radioPlayer.metaData.title
|
||||
title: radioPlayer._name
|
||||
}
|
||||
|
||||
onNextRequested: radioPlayer.playNext()
|
||||
|
||||
onPreviousRequested: radioPlayer.playPrev()
|
||||
|
||||
onPauseRequested:{
|
||||
radioPlayer.pauseStream();
|
||||
}
|
||||
|
||||
onPlayRequested: {
|
||||
radioPlayer.resumeStream();
|
||||
}
|
||||
onPlayPauseRequested: {
|
||||
radioPlayer.isPaused ? radioPlayer.playStream() : radioPlayer.pauseStream();
|
||||
}
|
||||
onStopRequested: {
|
||||
radioPlayer.pauseStream();
|
||||
}
|
||||
|
||||
onOpenUriRequested: message.lastMessage = "Requested to open uri \"" + url + "\""
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
import QtQuick 2.0
|
||||
import QtMultimedia 5.6
|
||||
import QtQuick.LocalStorage 2.0
|
||||
|
||||
import "../helpers/jsFunctions.js" as JsFunctions
|
||||
import "../helpers/db.js" as Favorites
|
||||
import "../items"
|
||||
|
||||
MediaPlayer {
|
||||
// Media info from clicking play
|
||||
property string _stationuuid: ""
|
||||
property string _name: ""
|
||||
property string _favicon: ""
|
||||
property string _cc: ""
|
||||
property string _tags: ""
|
||||
property string _codec: ""
|
||||
property string _bitrate: ""
|
||||
property string _hls: ""
|
||||
property string _url_resolved: ""
|
||||
property string _homepage: ""
|
||||
// property string _votes: ""
|
||||
// property string _plays: "" // For future implementation?!
|
||||
// property string _trend: ""
|
||||
property bool _favorite: false
|
||||
//--------------------------------
|
||||
property bool playerPageOpen: false
|
||||
property string radioId: ""
|
||||
property string metaInfo: metaData.title ? metaData.title : ""
|
||||
property string radioArtist: ""
|
||||
property string radioSong: ""
|
||||
property bool radioVideo: false
|
||||
property bool radioAudio: false
|
||||
property string radioCountryName
|
||||
property string radioHLS: JsFunctions.getHLS(_hls)
|
||||
property string radioCodec: JsFunctions.getCodec(_codec)
|
||||
property string radioBitrate: JsFunctions.getBitrate(_bitrate)
|
||||
property real radioBufferProgress: bufferProgress
|
||||
property int radioStatus
|
||||
property string radioStatusString
|
||||
property bool isPlaying: false
|
||||
property bool isPaused: false
|
||||
property int stationOk: 0
|
||||
property int maxTagClicks: 0
|
||||
property int playlistCount: playlist.count -1
|
||||
property int playlistIndex: Favorites.getSetting("playlistIndex",-1)
|
||||
property ListModel playHistory: ListModel {id: playHistory}
|
||||
property ListModel playlist: ListModel {id: playlist}
|
||||
property QDtimer timer: QDtimer {
|
||||
id: qdTimer
|
||||
interval: 200; running: false; repeat: false
|
||||
}
|
||||
|
||||
autoPlay: false
|
||||
autoLoad: true
|
||||
|
||||
onPlaying: if (!playerPageOpen) pageStack.push("../pages/RadioPlayerPage.qml")
|
||||
|
||||
onMetaInfoChanged: {
|
||||
if (metaInfo.search(" - ") > -1) {
|
||||
var res = metaInfo.split(" - ")
|
||||
radioArtist = res[0]
|
||||
radioSong = res[1]
|
||||
} else {
|
||||
radioArtist = metaInfo
|
||||
radioSong = ""
|
||||
}
|
||||
}
|
||||
|
||||
onStationOkChanged: {
|
||||
if (stationOk === 1) {
|
||||
setStationClick()
|
||||
getStationFavorite(_stationuuid)
|
||||
playStream()
|
||||
stationOk === 0
|
||||
reloadDbData()
|
||||
//if (_favorite) allradioSettings.setValue("currentFavorite",playlistIndex)
|
||||
}
|
||||
}
|
||||
|
||||
on_StationuuidChanged: {
|
||||
radioCountryName = radioBrowser.getCountryName(_cc)
|
||||
stop()
|
||||
source = ""
|
||||
radioVideo = false
|
||||
radioAudio = false
|
||||
isPaused = false
|
||||
isPlaying = false
|
||||
stationOk = 0
|
||||
getStationUrl(_stationuuid);
|
||||
}
|
||||
|
||||
onHasVideoChanged: if (hasVideo) radioVideo = true
|
||||
onHasAudioChanged: if (hasAudio) radioAudio = true
|
||||
|
||||
onError: {
|
||||
notification.category = "Error"
|
||||
notification.summary = _name
|
||||
notification.body = errorString
|
||||
notification.publish()
|
||||
radioPlayer.stopStream()
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
switch (status) {
|
||||
case 1: status1();break; // NoMedia
|
||||
case 2: status2();break; // Loading
|
||||
case 3: status3();break; // Loaded
|
||||
case 4: status4();break; // Buffering
|
||||
case 5: status5();break; // Stalled
|
||||
case 6: status6();break; // Buffered
|
||||
case 7: status7();break; // EndOfMedia
|
||||
case 8: status8();break; // InvalidMedia
|
||||
case 9: status9();break; // UnknownStatus
|
||||
}
|
||||
}
|
||||
|
||||
function status1 () { // NoMedia
|
||||
radioStatus = status
|
||||
radioStatusString = "No Media"
|
||||
}
|
||||
|
||||
function status2 () { // Loading
|
||||
radioStatus = status
|
||||
radioStatusString = "Loading"
|
||||
}
|
||||
|
||||
function status3 () { // Loaded
|
||||
radioStatus = status
|
||||
radioStatusString = "Loaded"
|
||||
}
|
||||
|
||||
function status4 () { // Buffering
|
||||
radioStatus = status
|
||||
radioStatusString = "Buffering"
|
||||
}
|
||||
|
||||
function status5 () { // Stalled
|
||||
radioStatus = status
|
||||
radioStatusString = "Stalled"
|
||||
notification.category = "Status"
|
||||
notification.summary = _name
|
||||
notification.body = "Stalled"
|
||||
notification.publish()
|
||||
radioPlayer.stopStream()
|
||||
}
|
||||
|
||||
function status6 () { // Buffered
|
||||
radioStatus = status
|
||||
radioStatusString = "Buffered"
|
||||
}
|
||||
|
||||
function status7 () { // EndOfMedia
|
||||
radioStatus = status
|
||||
radioStatusString = "End Of Media"
|
||||
notification.category = "Status"
|
||||
notification.summary = _name
|
||||
notification.body = "End of media"
|
||||
notification.publish()
|
||||
radioPlayer.resumeStream()
|
||||
}
|
||||
|
||||
function status8 () { // InvalidMedia
|
||||
radioStatus = status
|
||||
radioStatusString = "Invalid Media"
|
||||
notification.category = "Status"
|
||||
notification.summary = _name
|
||||
notification.body = "Invalid media"
|
||||
notification.publish()
|
||||
radioPlayer.stopStream()
|
||||
}
|
||||
|
||||
function status9 () { // UnknownStatus
|
||||
radioStatus = status
|
||||
radioStatusString = "Unknown Status"
|
||||
}
|
||||
|
||||
function stopStream() { // stop and clear stream
|
||||
source = ""
|
||||
isPaused = false
|
||||
isPlaying = false
|
||||
radioArtist = ""
|
||||
radioSong = ""
|
||||
radioVideo = false
|
||||
radioAudio = false
|
||||
stationOk = 3
|
||||
_stationuuid = ""
|
||||
_name = ""
|
||||
_favicon = ""
|
||||
_cc = ""
|
||||
_tags = ""
|
||||
_codec = ""
|
||||
_bitrate = ""
|
||||
_hls = ""
|
||||
_homepage = ""
|
||||
stop()
|
||||
}
|
||||
|
||||
function playNext() {
|
||||
if (playlistIndex < playlistCount) playlistIndex = playlistIndex + 1
|
||||
loadPlaylistSelected()
|
||||
}
|
||||
|
||||
function playPrev() {
|
||||
if (playlistIndex <= playlistCount) playlistIndex = playlistIndex - 1
|
||||
loadPlaylistSelected()
|
||||
}
|
||||
|
||||
function videoPause() {
|
||||
source = ""
|
||||
stop()
|
||||
}
|
||||
|
||||
function pauseStream() {
|
||||
isPlaying = false
|
||||
source = ""
|
||||
stop()
|
||||
}
|
||||
|
||||
function resumeStream() {
|
||||
isPlaying = true
|
||||
isPaused = false
|
||||
playStream()
|
||||
}
|
||||
|
||||
function playStream() {
|
||||
//console.log(" ********** URL : "+_url_resolved)
|
||||
source = Qt.resolvedUrl(_url_resolved)
|
||||
play()
|
||||
isPlaying = true
|
||||
isPaused = false
|
||||
qdTimer.start()
|
||||
if (_favorite) Favorites.setSetting("playlistIndex",playlistIndex)
|
||||
//appStartPlay = false
|
||||
}
|
||||
|
||||
function tryagain() {
|
||||
tryTimer.running = true
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setStationClick() {
|
||||
Favorites.setStationClicked(JsFunctions.getTimeStamp(),_stationuuid,_name,_cc,_homepage,_url_resolved,_favicon,_tags,_codec,_bitrate,_hls,_favorite)
|
||||
}
|
||||
|
||||
function setStationFavorite(stationuuid,name,countrycode,homepage,url_resolved,favicon,tags,codec,bitrate,hls,favorite) {
|
||||
Favorites.setStationFavorite(stationuuid,name,countrycode,homepage,url_resolved,favicon,tags,codec,bitrate,hls,favorite)
|
||||
}
|
||||
|
||||
function getStationFavorite(id){
|
||||
_favorite = Favorites.getStationFavorite(id)
|
||||
}
|
||||
|
||||
function reloadDbData() {
|
||||
Favorites.getStationRecentClicked(playHistory,15)
|
||||
Favorites.getFavorites(playlist,"myclickcount",10000)
|
||||
//Favorites.getStationMostClickedFav(radioPlayermostPlayed,settings._nrOfFavoritePreview)
|
||||
//Favorites.getCountryRecentClicked(playedCountries,2)
|
||||
//Favorites.getTagsRecentClicked(playedTags,10)
|
||||
//Favorites.getMostPlayedFavorites(mostPlayedFavorites,15)
|
||||
}
|
||||
|
||||
function loadPlaylistSelected(){
|
||||
if (playlist.get(playlistIndex).url_resolved) {
|
||||
_favicon = playlist.get(playlistIndex).favicon
|
||||
_name = playlist.get(playlistIndex).name
|
||||
_cc = playlist.get(playlistIndex).countrycode
|
||||
_tags = playlist.get(playlistIndex).tags
|
||||
_codec = playlist.get(playlistIndex).codec//getCodec(model.codec)
|
||||
_bitrate = playlist.get(playlistIndex).bitrate //getBitrate(model.bitrate)
|
||||
_hls = playlist.get(playlistIndex).hls
|
||||
_url_resolved = playlist.get(playlistIndex).url_resolved
|
||||
_homepage = playlist.get(playlistIndex).homepage
|
||||
_stationuuid = playlist.get(playlistIndex).stationuuid
|
||||
_favorite = playlist.get(playlistIndex).favorite
|
||||
isPlaying = true
|
||||
isPaused = false
|
||||
|
||||
playStream()
|
||||
// pageStack.push("RadioPlayerPage.qml")
|
||||
}
|
||||
}
|
||||
|
||||
function loadRecentPlay(){
|
||||
if (playHistory.get(0).url_resolved) {
|
||||
_favicon = playHistory.get(0).favicon
|
||||
_name = playHistory.get(0).name
|
||||
_cc = playHistory.get(0).countrycode
|
||||
_tags = playHistory.get(0).tags
|
||||
_codec = playHistory.get(0).codec//getCodec(model.codec)
|
||||
_bitrate = playHistory.get(0).bitrate //getBitrate(model.bitrate)
|
||||
_hls = playHistory.get(0).hls
|
||||
_url_resolved = playHistory.get(0).url_resolved
|
||||
_homepage = playHistory.get(0).homepage
|
||||
_stationuuid = playHistory.get(0).stationuuid
|
||||
_favorite = playHistory.get(0).favorite
|
||||
isPlaying = false
|
||||
isPaused = true
|
||||
///if (_favorite) playlistCount = Favorites.getSetting("playlistIndex",-1)
|
||||
//playlistIndex = allradioSettings.value("currentFavorite",-1)
|
||||
// pageStack.push("RadioPlayerPage.qml")
|
||||
}
|
||||
}
|
||||
|
||||
function loadRandomPlay(){
|
||||
var rnd = Math.floor(Math.random() * playlist.count)
|
||||
if (playlist.get(rnd).url_resolved) {
|
||||
_favicon = playlist.get(rnd).favicon
|
||||
_name = playlist.get(rnd).name
|
||||
_cc = playlist.get(rnd).countrycode
|
||||
_tags = playlist.get(rnd).tags
|
||||
_codec = playlist.get(rnd).codec//getCodec(model.codec)
|
||||
_bitrate = playlist.get(rnd).bitrate //getBitrate(model.bitrate)
|
||||
_hls = playlist.get(rnd).hls
|
||||
_url_resolved = playlist.get(rnd).url_resolved
|
||||
_homepage = playlist.get(rnd).homepage
|
||||
_stationuuid = playlist.get(rnd).stationuuid
|
||||
_favorite = playlist.get(rnd).favorite
|
||||
isPlaying = false
|
||||
isPaused = true
|
||||
// pageStack.push("RadioPlayerPage.qml")
|
||||
}
|
||||
}
|
||||
|
||||
function updateMprisMetadata(){
|
||||
mprisPlayer.song = metaInfo ? metaInfo : ""
|
||||
mprisPlayer.artist = radioStation === "" ? "AllRadio" : radioStation
|
||||
updatePlaybackStatus()
|
||||
}
|
||||
|
||||
function updatePlaybackStatus (){
|
||||
switch (playMusic.playbackState) {
|
||||
case Audio.PlayingState:
|
||||
mprisPlayer.playbackStatus = Mpris.Playing
|
||||
break;
|
||||
|
||||
case Audio.PausedState:
|
||||
mprisPlayer.setCanPause(false)
|
||||
mprisPlayer.playbackStatus = Mpris.Paused
|
||||
break;
|
||||
case Audio.StoppedState:
|
||||
mprisPlayer.playbackStatus = Mpris.Paused
|
||||
break;
|
||||
default:
|
||||
mprisPlayer.playbackStatus = Mpris.Paused
|
||||
}
|
||||
}
|
||||
// Register as radio station click on community radio and get station info from Community Radio and save it to Db. Initiate playback.
|
||||
function getStationUrl(id) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === 4 && req.status < 300) {
|
||||
var temp = req.responseText
|
||||
var ok = temp.indexOf('status ok="true"') !== -1
|
||||
if (ok) {
|
||||
stationOk = 1
|
||||
} else {
|
||||
stationOk = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
req.open("post", radioBrowser.serverUrl + "/xml/url/" +id);
|
||||
req.setRequestHeader('User-Agent',radioBrowser._useragent);
|
||||
req.send();
|
||||
}
|
||||
|
||||
Component.onCompleted: {reloadDbData();_favorite ? loadPlaylistSelected() : loadRecentPlay()}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import QtQuick 2.0
|
||||
import Nemo.DBus 2.0
|
||||
|
||||
Item {
|
||||
property bool enabled: false
|
||||
function request(){
|
||||
var method = "req_display"+(enabled?"":"_cancel")+"_blanking_pause";
|
||||
dbif.call(method, [])
|
||||
}
|
||||
|
||||
onEnabledChanged: {
|
||||
request();
|
||||
}
|
||||
|
||||
DBusInterface {
|
||||
id: dbif
|
||||
|
||||
service: "com.nokia.mce"
|
||||
path: "/com/nokia/mce/request"
|
||||
iface: "com.nokia.mce.request"
|
||||
|
||||
bus: DBusInterface.SystemBus
|
||||
}
|
||||
Timer {
|
||||
running: parent.enabled
|
||||
interval: 15000
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if(parent.enabled) {
|
||||
parent.request()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if(enabled){
|
||||
enabled=false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
Timer {
|
||||
id: sleepTimer
|
||||
interval: 60000
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (sleepTime == 1) { radioPlayer.pauseStream();sleepTime = 0;} else sleepTime = (sleepTime = sleepTime -1);
|
||||
}
|
||||
running: sleepTime > 0
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
//import "../helpers/jsFunctions.js" as JS
|
||||
|
||||
Column {
|
||||
id: column
|
||||
spacing: Theme.paddingMedium
|
||||
anchors.centerIn: parent
|
||||
Timer {
|
||||
id: spTimer
|
||||
interval: 5000; running: visible ? true : false; repeat: false
|
||||
onTriggered: radioBrowser.getRandom(radioBrowser.serverUrl)
|
||||
}
|
||||
|
||||
Image {
|
||||
id: logo
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: Theme.itemSizeHuge * 1.5
|
||||
width: height
|
||||
smooth: true
|
||||
source: "../images/community.png"
|
||||
ColorOverlay {
|
||||
anchors.fill: parent
|
||||
source: parent
|
||||
color: Theme.highlightColor
|
||||
}
|
||||
}
|
||||
|
||||
BusyLabel {
|
||||
width: parent.width
|
||||
text: radioBrowser.serversModel.count > 0 ? qsTr("Found")+": "+radioBrowser.serversModel.count + " "+qsTr("servers") : qsTr("Searching servers")
|
||||
running: radioBrowser.serversModel.count < 1
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
BusyLabel {
|
||||
width: parent.width
|
||||
visible: radioBrowser.serversModel.count > 0
|
||||
running: visible
|
||||
text: qsTr("Connecting")
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
Label {
|
||||
visible: radioBrowser.serversModel.count > 0
|
||||
text: radioBrowser.server
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.highlightColor
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
/* Button {
|
||||
visible: radioBrowser.serversModel.count > 1 && !spTimer.running
|
||||
anchors.topMargin: Theme.paddingLarge
|
||||
text: qsTr("Try another server")
|
||||
onClicked: radioBrowser.getRandom(radioBrowser.serverUrl)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
} */
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
// TODO: Investigate using one quarter of the image mirrored in two directions
|
||||
// TODO: Investigate using a scaled down version of the image
|
||||
|
||||
Item {
|
||||
id: valuePicker
|
||||
|
||||
property int value
|
||||
property int max
|
||||
property int min
|
||||
|
||||
property real _scaleRatio: valueCircle.width / 408
|
||||
|
||||
width: valueCircle.width
|
||||
height: valueCircle.height
|
||||
|
||||
onValueChanged: {
|
||||
value = (value < 1 ? 1 : (value > max ? max : value))
|
||||
|
||||
if (mouse.changingProperty == 0) {
|
||||
var delta = (value - valueIndicator.value)
|
||||
valueIndicator.value += (delta % (max - 1))
|
||||
}
|
||||
}
|
||||
|
||||
function _xTranslation(value, bound) {
|
||||
// Use sine to map range of 0-bound to the X translation of a circular locus (-1 to 1)
|
||||
return Math.sin((value % bound) / bound * Math.PI * 2)
|
||||
}
|
||||
|
||||
function _yTranslation(value, bound) {
|
||||
// Use cosine to map range of 0-bound to the Y translation of a circular locus (-1 to 1)
|
||||
return Math.cos((value % bound) / bound * Math.PI * 2)
|
||||
}
|
||||
|
||||
Image {
|
||||
id: valueCircle
|
||||
width: page.width * 0.75
|
||||
height: width
|
||||
source: "../images/timepicker.png"
|
||||
opacity: 0.2
|
||||
}
|
||||
|
||||
GlassItem {
|
||||
id: valueIndicator
|
||||
falloffRadius: 0.22
|
||||
radius: 0.25
|
||||
anchors.centerIn: valueCircle
|
||||
color: mouse.changingProperty == 2 ? Theme.highlightColor : Theme.primaryColor
|
||||
|
||||
property real value
|
||||
|
||||
transform: Translate {
|
||||
// The ss band is 72px wide, ending at 204px from the center
|
||||
x: _scaleRatio*168 * _xTranslation(valueIndicator.value, max)
|
||||
y: -_scaleRatio*168 * _yTranslation(valueIndicator.value, max)
|
||||
}
|
||||
|
||||
Behavior on value {
|
||||
id: valueAnimation
|
||||
SmoothedAnimation { velocity: 80 }
|
||||
enabled: !mouse.isMoving || mouse.isLagging
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
|
||||
property int changingProperty
|
||||
property bool isMoving
|
||||
property bool isLagging
|
||||
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
|
||||
function radiusForCoord(x, y) {
|
||||
// Return the distance from the mouse position to the center
|
||||
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
|
||||
}
|
||||
|
||||
function angleForCoord(x, y) {
|
||||
// Return the angular position in degrees, rising anticlockwise from the positive X-axis
|
||||
var result = Math.atan(y / x) / (Math.PI * 2) * 360
|
||||
|
||||
// Adjust for various quadrants
|
||||
if (x < 0) {
|
||||
result += 180
|
||||
} else if (y < 0) {
|
||||
result += 360
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function remapAngle(value, bound) {
|
||||
// Return the angle in degrees mapped to the adjusted range 0 - (bound-1) and
|
||||
// translated to the clockwise from positive Y-axis orientation
|
||||
return Math.round(bound - (((value - 90) / 360) * bound)) % bound
|
||||
}
|
||||
|
||||
function remapMouse(mouseX, mouseY) {
|
||||
// Return the mouse coordinates in cartesian coords relative to the circle center
|
||||
return { x: mouseX - (width / 2), y: 0 - (mouseY - (height / 2)) }
|
||||
}
|
||||
|
||||
function propertyForRadius(radius) {
|
||||
// Return the property associated with clicking at radius distance from the center
|
||||
if (radius < mouse.width / 2) {
|
||||
return 2 // Minutes
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function updateForAngle(angle) {
|
||||
// Update the selected property for the specified angular position
|
||||
// Minutes
|
||||
// Map angular position to 0-59
|
||||
var m = remapAngle(angle, max)
|
||||
|
||||
// Round single touch to the nearest 5 min mark
|
||||
if (!isMoving) m = (Math.round(m/5) * 5) % (max - 1)
|
||||
|
||||
var delta = (m - valueIndicator.value) % (max - 1)
|
||||
|
||||
// It is not possible to make jumps of more than 30 minutes - reverse the direction
|
||||
if (delta > 60) {
|
||||
delta -= max
|
||||
} else if (delta < -60) {
|
||||
delta += max
|
||||
}
|
||||
if (isMoving && isLagging) {
|
||||
if (Math.abs(delta) < 2) {
|
||||
isLagging = false
|
||||
}
|
||||
}
|
||||
|
||||
valueIndicator.value += delta
|
||||
|
||||
valuePicker.value = m
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
console.log("PRESSED")
|
||||
var coords = remapMouse(mouseX, mouseY)
|
||||
var radius = radiusForCoord(coords.x, coords.y)
|
||||
|
||||
changingProperty = propertyForRadius(radius)
|
||||
if (changingProperty != 0) {
|
||||
preventStealing = true
|
||||
var angle = angleForCoord(coords.x, coords.y)
|
||||
|
||||
isLagging = true
|
||||
updateForAngle(angle)
|
||||
} else {
|
||||
// Outside the minutes band - allow pass through to underlying component
|
||||
preventStealing = false
|
||||
}
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (changingProperty > 0) {
|
||||
var coords = remapMouse(mouseX, mouseY)
|
||||
var angle = angleForCoord(coords.x, coords.y)
|
||||
|
||||
isMoving = true
|
||||
updateForAngle(angle)
|
||||
}
|
||||
}
|
||||
onReleased: {
|
||||
changingProperty = 0
|
||||
isMoving = false
|
||||
isLagging = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import QtQuick 2.0
|
||||
import QtMultimedia 5.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Rectangle {
|
||||
id: videoRect
|
||||
//property bool keepScreenOn: Qt.application.active && visible ? true : false
|
||||
property bool stateVisible: radioPlayer.radioVideo && radioPlayer.isPlaying
|
||||
property alias videoSource: output.source
|
||||
//property alias source: output.source
|
||||
opacity: 0
|
||||
color: "black"
|
||||
|
||||
//JupiiItem {id: jupii}
|
||||
|
||||
onOpacityChanged: {
|
||||
opacity === 0 ? visible = false : visible = true
|
||||
}
|
||||
|
||||
states: [
|
||||
State { when: videoRect.stateVisible;
|
||||
PropertyChanges { target: videoRect; opacity: 1.0 }},
|
||||
State { when: !videoRect.stateVisible;
|
||||
PropertyChanges { target: videoRect; opacity: 0.0 }}
|
||||
]
|
||||
|
||||
transitions: [ Transition { NumberAnimation { property: "opacity"; duration: 500}} ]
|
||||
|
||||
/* ScreenBlank {
|
||||
id: screenBlank
|
||||
enabled: keepScreenOn
|
||||
} */
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: videoOverlay.stateVisible = !videoOverlay.stateVisible
|
||||
}
|
||||
|
||||
VideoOutput {
|
||||
id: output
|
||||
anchors.fill: parent
|
||||
source: null
|
||||
fillMode: VideoOutput.PreserveAspectFit
|
||||
}
|
||||
|
||||
/* Timer {
|
||||
interval: 5000; running: videoOverlay.visible ; repeat: false
|
||||
onTriggered: videoOverlay.stateVisible = false
|
||||
} */
|
||||
|
||||
Item {
|
||||
id: videoOverlay
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
|
||||
property bool stateVisible: true
|
||||
|
||||
opacity: 1
|
||||
onOpacityChanged: {
|
||||
opacity === 0 ? visible = false : visible = true
|
||||
}
|
||||
|
||||
states: [
|
||||
State { when: videoOverlay.stateVisible;
|
||||
PropertyChanges { target: videoOverlay; opacity: 1.0 }},
|
||||
State { when: !videoOverlay.stateVisible;
|
||||
PropertyChanges { target: videoOverlay; opacity: 0.0 }}
|
||||
]
|
||||
transitions: [ Transition { NumberAnimation { property: "opacity"; duration: 250}} ]
|
||||
}
|
||||
// Component.onCompleted: {playerPanel.open = false;radioPlayer.videoPlayerPageOpen=true;}
|
||||
// Component.onDestruction: radioPlayer.videoPlayerPageOpen=false //Component.onDestruction: {if (radioPlayer.radioPlaying) playerPanel.open = true;radioPlayer.radioPlayerPageOpen = false}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user