ny commit

This commit is contained in:
Niels
2025-05-28 20:47:14 +02:00
commit d4cd7f8bdc
324 changed files with 7462 additions and 0 deletions
+41
View File
@@ -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" }
}
}
}
+142
View File
@@ -0,0 +1,142 @@
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._countrycode === "" ? radioPlayer._countrycode ? "../images/bycountry_t.png" : "" : "../flags/"+radioPlayer._countrycode.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
}
}
}
+17
View File
@@ -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()
}
}
+162
View File
@@ -0,0 +1,162 @@
// 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
// Properties to be used in application -------------------------------------------------
property ListModel serversModel : ListModel { id: serversModel }
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 string lookup: "http://all.api.radio-browser.info/json/servers" //"http://all.api.radio-browser.info/json/servers"
// ---------------------------------------------------------------------------------------
onOnlineChanged: {
//console.log("onOnlineChanged")
if (online && serverUrl !== "") {
countriesModel.source = serverUrl + "/xml/countrycodes?hidebroken=true"
//tagsModel.source = serverUrl + "/xml/tags?hidebroken=true"
}
}
function getServer(s,u) {
//console.log("getServer")
stationCount = 0
tagCount = 0
countryCount = 0
server = s
serverUrl = u
getStats()
}
function getRandom() {
//console.log("getRandom")
if (serversModel.count > 0) {
var random = Math.floor((Math.random() * serversModel.count) + 1) - 1
serverUrl = serversModel.get(random).serverUrl
server = serversModel.get(random).server
//console.log("getRandom: "+server)
getStats()
} //else getList()
}
function getList() {
//console.log("getList")
var req = new XMLHttpRequest();
req.open("get", lookup,true);
req.setRequestHeader('User-Agent',_useragent);
req.timeout = 4000; // Set timeout to 4 seconds (4000 milliseconds)
req.ontimeout = function () { console.log("Timed out!!!"); }
//console.log("server 2")
req.onreadystatechange = function () {
//console.log(console.log("getList: "+req.status))
if (req.readyState === 4 && req.status === 200) {
var obj = JSON.parse(req.responseText)
serversModel.clear()
for (var key in obj) {
addIfNotExist(obj[key])
}
getRandom()
} else if (req.readyState === 4 && req.status === 502) lookup="http://de1.api.radio-browser.info/json/servers"
};
req.send();
}
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})
}
function getStats() {
//console.log("getStats")
var req = new XMLHttpRequest();
req.open("get", serverUrl+"/json/stats",true);
req.setRequestHeader('User-Agent',_useragent);
req.onreadystatechange = function () {
//console.log("XMLHTTPREQUEST READYSTATE: "+req.readyState + " STATUS: "+req.status)
if (req.readyState === 4 && req.status === 200) {
//console.log("STATUS:"+req.status)
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}
}
} else if (req.readyState === 4 && req.status === 502) getRandom()
};
req.send();
}
function upVote(stationuuid,returnValue) {
var req = new XMLHttpRequest();
var ret = false
req.open("get", serverUrl+"/json/vote/"+stationuuid,true);
req.setRequestHeader('User-Agent',_useragent);
req.onreadystatechange = function () {
//console.log("XMLHTTPREQUEST READYSTATE: "+req.readyState + " STATUS: "+req.status)
if (req.readyState === 4 && req.status === 200) {
var obj = req.response.split("{").pop();
obj = JSON.parse("{"+obj)
//console.log(obj.ok)
if (obj.ok) {
//stationCount = obj.stations-obj.stations_broken
//tagCount = obj.tags
if (obj.ok) {returnValue=true;console.log(" ****** VOTED *****")} else {returnValue=false;console.log(" ****** NOT VOTED *****")}
}
return ret
}
};
req.send();
}
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)
}
}
}
}
+392
View File
@@ -0,0 +1,392 @@
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 _countrycode: ""
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: ""
// property string _trend: ""
property bool _favorite: false
//--------------------------------
// property bool videoP: false
property bool playerPageOpen: false
// property bool jupiiOn: 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: 3
property int maxTagClicks: 0
property int playlistCount: playlist.count - 1
property int playlistIndex: allradioSettings.value("currentFavorite",-1)
property QDtimer timer: QDtimer {id: qdTimer}
//property string videoOut: ""
// property ListModel mostPlayedFavorites: ListModel {id: mostPlayedFavorites}
//videoOutput: videoOut
// property variant magnitudeArray: null
// property int millisecondsPerBar: 68
property ListModel playHistory: ListModel {id: playHistory}
property ListModel playlist: ListModel {id: playlist}
autoPlay: false
autoLoad: true
//on_FavoriteChanged: {setStationFavorite(_stationuuid,_name,_countrycode,_homepage,_url_resolved,_favicon,_tags,_codec,_bitrate,_hls,_favorite);Favorites.getMostPlayedFavorites(mostPlayedFavorites,15)}
onPlaying: if (!playerPageOpen) pageStack.push("../pages/RadioPlayerPage.qml")
// onPlaylistIndexChanged: loadPlaylistSelected()
onMetaInfoChanged: {
// console.log(" ******* METAINFO: "+metaInfo)
if (metaInfo.search(" - ") > -1) {
var res = metaInfo.split(" - ")
radioArtist = res[0]
radioSong = res[1]
} else {
radioArtist = metaInfo
radioSong = ""
}
}
onRadioAudioChanged: {
// if (hasVideo) console.log(" *** VIDEO"); else console.log(" *** AUDIO")
}
onStationOkChanged: {
// console.log("StationOK?: "+stationOk)
if (stationOk === 1) {
setStationClick()
getStationFavorite(_stationuuid)
playStream()
stationOk === 0
reloadDbData()
if (_favorite) allradioSettings.setValue("currentFavorite",playlistIndex)
}
}
on_StationuuidChanged: { //if (_stationuuid !== "") {getStationUrl(_stationuuid);radioPlayUrl = _url_resolved} else radioPlayUrl = ""
radioCountryName = radioBrowser.getCountryName(_countrycode)
stop()
source = ""
//metaInfo = ""
radioVideo = false
radioAudio = false
isPaused = false
isPlaying = false
stationOk = 3
getStationUrl(_stationuuid);
}
//onIsPausedChanged: if (_paused) {
//radioPlaying = false
///radioPaused = true
// radioSource = ""
// metaInfo = ""
// if(radioVideo) {
// videoPlayer.visible = false
// radioSource = ""
// }
// }
onHasVideoChanged: if (hasVideo) radioVideo = true
onHasAudioChanged: if (hasAudio) radioAudio = true
function stopStream() { // stop and clear stream
source = ""
isPaused = false
isPlaying = false
radioArtist = ""
radioSong = ""
radioVideo = false
radioAudio = false
stationOk = 3
_stationuuid = ""
_name = ""
_favicon = ""
_countrycode = ""
_tags = ""
_codec = ""
_bitrate = ""
_hls = ""
_homepage = ""
stop()
// metaInfo = ""
}
function videoPause() {
source = ""
stop()
}
function pauseStream() { // stop stream without clear
isPaused = true
isPlaying = false
source = ""
stop()
// metaInfo = ""
}
function resumeStream() {
isPlaying = true
isPaused = false
playStream()
}
function playStream() { // resume paused stream
//radioSource = ""
source = _url_resolved
play()
isPlaying = true
isPaused = false
qdTimer.start()
// play()
}
onError: {
notification.category = "Error"
notification.summary = _name
//notification.subText = _name
notification.body = errorString
notification.publish()
radioPlayer.stopStream()
}
/* onRadioStatusChanged: {
notification.body = radioStatusString
notification.publish()
}*/
onStatusChanged: {
console.log(" ___ STATUS: "+status)
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 tryagain() {
tryTimer.running = true
}
function status1 () { // NoMedia
radioStatus = status
radioStatusString = "No Media"
console.log("Status: No Media")
}
function status2 () { // Loading
radioStatus = status
radioStatusString = "Loading"
console.log("Status: Loading")
}
function status3 () { // Loaded
radioStatus = status
radioStatusString = "Loaded"
console.log("Status: Loaded")
}
function status4 () { // Buffering
radioStatus = status
radioStatusString = "Buffering"
console.log("Status: Buffering")
}
function status5 () { // Stalled
radioStatus = status
radioStatusString = "Stalled"
notification.category = "Status"
notification.summary = _name
//notification.subText = _name
notification.body = "Stalled"
notification.publish()
console.log("Status: Stalled")
radioPlayer.stopStream()
}
function status6 () { // Buffered
radioStatus = status
radioStatusString = "Buffered"
console.log("Status: Buffered")
}
function status7 () { // EndOfMedia
/* if (errorCount<4) {
//errorCount = errorCount + 1
tryTimer.start()
}else{ */
radioStatus = status
radioStatusString = "End Of Media"
notification.category = "Status"
notification.summary = _name
//notification.subText = _name
notification.body = "End of media"
notification.publish()
console.log("Status: End Of Media")
radioPlayer.stopStream()
// }
}
function status8 () { // InvalidMedia
radioStatus = status
radioStatusString = "Invalid Media"
notification.category = "Status"
notification.summary = _name
//notification.subText = _name
notification.body = "Invalid media"
notification.publish()
console.log("Status: Invalid Media")
radioPlayer.stopStream()
}
function status9 () { // UnknownStatus
radioStatus = status
radioStatusString = "Unknown Status"
console.log("Status: Unknown Status")
}
function getStationUrl(id) { // Register as radio station click on community radio and get station info from Community Radio and save it to Db. Initiate playback.
var req = new XMLHttpRequest();
req.open("post", radioBrowser.serverUrl + "/xml/url/" +id, true);
// console.log(radioBrowser.serverUrl)
req.responseType = "document";
req.setRequestHeader('User-Agent',radioBrowser._useragent);
req.onreadystatechange = function () {
if (req.readyState === 4 && req.status === 200) {
var temp = req.responseText
var ok = temp.indexOf('status ok="true"') !== -1
// console.log("OK: "+ok)
if (ok) {
stationOk = 1
} else {
stationOk = 0
}
} //else if (req.readyState === 4) {stationOk = 2}
};
req.send();
}
function setStationClick() {
//getStationFavorite(_stationuuid)
Favorites.setStationClicked(JsFunctions.getTimeStamp(),_stationuuid,_name,_countrycode,_homepage,_url_resolved,_favicon,_tags,_codec,_bitrate,_hls,_favorite)
// property bool favo: isFavorite(stationuuid) ? true : false
//getIfFavorite(_stationuuid)
//getIfFavorite(_stationuuid)
} // myclicktimestamp,id,name,countrycode,homepage,radiourlresolved,favicon,tagslist,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,"name",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
_countrycode = 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
_countrycode = 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
// pageStack.push("RadioPlayerPage.qml")
}
}
function loadRandomPlay(){
var rnd = Math.floor(Math.random() * playlistCount)
if (playHistory.get(rnd).url_resolved) {
_favicon = playHistory.get(rnd).favicon
_name = playHistory.get(rnd).name
_countrycode = playHistory.get(rnd).countrycode
_tags = playHistory.get(rnd).tags
_codec = playHistory.get(rnd).codec//getCodec(model.codec)
_bitrate = playHistory.get(rnd).bitrate //getBitrate(model.bitrate)
_hls = playHistory.get(rnd).hls
_url_resolved = playHistory.get(rnd).url_resolved
_homepage = playHistory.get(rnd).homepage
_stationuuid = playHistory.get(rnd).stationuuid
_favorite = playHistory.get(rnd).favorite
isPlaying = false
isPaused = true
// pageStack.push("RadioPlayerPage.qml")
}
}
Component.onCompleted: {reloadDbData();loadRecentPlay()}
}
+40
View File
@@ -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
}
}
}
+11
View File
@@ -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
}
+41
View File
@@ -0,0 +1,41 @@
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
//property alias busy: busyIndicator.running
anchors.centerIn: parent
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
}
}
Label {
text: radioBrowser.serversModel.count > 0 ? "Found: "+radioBrowser.serversModel.count + " servers" : "Searching for servers..."
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
visible: radioBrowser.serversModel.count > 0
text: "Connecting to:"
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
text: radioBrowser.server
font.pixelSize: Theme.fontSizeSmall
color: Theme.highlightColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
+175
View File
@@ -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
}
}
}
+75
View File
@@ -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}
}