mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2025-09-01 08:52:45 +00:00
Added Direct Play and websocket improvements
* [backend]: Websocket now automatically tries to reconnect if connection was lost, up to 3 times. * [backend]: Move more playback and resume logic to the backend, to avoid having it in multiple places within the QML. Regression: pausing playback sometimes halts the video player for an unknown reason. * [playback]: Sailfin will try to play without the server transcoding, if possible. * [ui]: added a debug page in the settings
This commit is contained in:
parent
a244c27b1a
commit
7e77abc173
13 changed files with 204 additions and 45 deletions
|
@ -31,15 +31,15 @@ import "../"
|
|||
|
||||
SilicaItem {
|
||||
id: playerRoot
|
||||
property alias item : mediaSource.item
|
||||
property JellyfinItem item
|
||||
property string title: item.name
|
||||
property alias resume: mediaSource.resumePlayback
|
||||
property bool resume
|
||||
property int progress
|
||||
readonly property bool landscape: videoOutput.contentRect.width > videoOutput.contentRect.height
|
||||
property MediaPlayer player
|
||||
readonly property bool hudVisible: !hud.hidden || player.error !== MediaPlayer.NoError
|
||||
property alias audioTrack: mediaSource.audioIndex
|
||||
property alias subtitleTrack: mediaSource.subtitleIndex
|
||||
property int audioTrack: 0
|
||||
property int subtitleTrack: 0
|
||||
|
||||
// Blackground to prevent the ambience from leaking through
|
||||
Rectangle {
|
||||
|
@ -47,13 +47,6 @@ SilicaItem {
|
|||
color: Theme.overlayBackgroundColor
|
||||
}
|
||||
|
||||
PlaybackManager {
|
||||
id: mediaSource
|
||||
apiClient: ApiClient
|
||||
mediaPlayer: player
|
||||
autoOpen: true
|
||||
}
|
||||
|
||||
VideoOutput {
|
||||
id: videoOutput
|
||||
source: player
|
||||
|
@ -69,7 +62,8 @@ SilicaItem {
|
|||
Label {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.horizontalPageMargin
|
||||
text: item.jellyfinId + "\n" + mediaSource.streamUrl + "\n"
|
||||
text: item.jellyfinId + "\n" + appWindow.playbackManager.streamUrl + "\n"
|
||||
+ (appWindow.playbackManager.playMethod == PlaybackManager.DirectPlay ? "Direct Play" : "Transcoding") + "\n"
|
||||
+ player.position + "\n"
|
||||
+ player.status + "\n"
|
||||
+ player.bufferProgress + "\n"
|
||||
|
@ -78,7 +72,7 @@ SilicaItem {
|
|||
+ player.errorString + "\n"
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
wrapMode: "WordWrap"
|
||||
visible: true
|
||||
visible: appWindow.showDebugInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +81,13 @@ SilicaItem {
|
|||
player: playerRoot.player
|
||||
}
|
||||
|
||||
function start() {
|
||||
appWindow.playbackManager.audioIndex = audioTrack
|
||||
appWindow.playbackManager.subtitleIndex = subtitleTrack
|
||||
appWindow.playbackManager.resumePlayback = resume
|
||||
appWindow.playbackManager.item = item
|
||||
}
|
||||
|
||||
function stop() {
|
||||
player.stop()
|
||||
}
|
||||
|
|
|
@ -33,12 +33,16 @@ ApplicationWindow {
|
|||
property bool _hasInitialized: false
|
||||
// The global mediaPlayer instance
|
||||
readonly property MediaPlayer mediaPlayer: _mediaPlayer
|
||||
readonly property PlaybackManager playbackManager: _playbackManager
|
||||
|
||||
// Data of the currently selected item. For use on the cover.
|
||||
property JellyfinItem itemData
|
||||
// Id of the collection currently browsing. For use on the cover.
|
||||
property string collectionId
|
||||
|
||||
// Bad way to implement settings, but it'll do for now.
|
||||
property bool showDebugInfo: false
|
||||
|
||||
//FIXME: proper error handling
|
||||
Connections {
|
||||
target: ApiClient
|
||||
|
@ -98,6 +102,14 @@ ApplicationWindow {
|
|||
autoPlay: true
|
||||
}
|
||||
|
||||
PlaybackManager {
|
||||
id: _playbackManager
|
||||
apiClient: ApiClient
|
||||
mediaPlayer: _mediaPlayer
|
||||
audioIndex: 0
|
||||
autoOpen: true
|
||||
}
|
||||
|
||||
// Keep the sytem alive while playing media
|
||||
KeepAlive {
|
||||
enabled: _mediaPlayer.playbackState == MediaPlayer.PlayingState
|
||||
|
|
|
@ -54,6 +54,7 @@ Page {
|
|||
//appWindow.orientation = landscape ? Orientation.Landscape : Orientation.Portrait
|
||||
videoPage.allowedOrientations = landscape ? Orientation.LandscapeMask : Orientation.PortraitMask
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
|
@ -62,6 +63,7 @@ Page {
|
|||
videoPlayer.stop()
|
||||
break;
|
||||
case PageStatus.Active:
|
||||
videoPlayer.start()
|
||||
appWindow.itemData = videoPage.itemData
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -73,10 +73,13 @@ BaseDetailPage {
|
|||
}
|
||||
}
|
||||
delegate: SongDelegate {
|
||||
id: songDelegate
|
||||
name: model.name
|
||||
artists: model.artists
|
||||
duration: model.runTimeTicks
|
||||
indexNumber: model.indexNumber
|
||||
onClicked: window.playbackManager.item = Qt.createQmlObject("import nl.netsoj.chris.Jellyfin 1.0;"
|
||||
+ "JellyfinItem { jellyfinId: \"" + model.id + "\"; apiClient: ApiClient; }", songDelegate, "nonexistent.qml");
|
||||
}
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
|
|
|
@ -39,6 +39,55 @@ Page {
|
|||
title: qsTr("Debug information")
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
text: qsTr("Show debug information")
|
||||
checked: appWindow.showDebugInfo
|
||||
onCheckedChanged: appWindow.showDebugInfo = checked
|
||||
}
|
||||
|
||||
SectionHeader {
|
||||
text: qsTr("Websocket")
|
||||
}
|
||||
|
||||
DetailItem {
|
||||
label: qsTr("Connection state")
|
||||
value: {
|
||||
var stateText
|
||||
switch( ApiClient.websocket.state) {
|
||||
case 0:
|
||||
//- Socket state
|
||||
stateText = qsTr("Unconnected");
|
||||
break;
|
||||
case 1:
|
||||
//- Socket state
|
||||
stateText = "Looking up host";
|
||||
break;
|
||||
case 2:
|
||||
//- Socket state
|
||||
stateText = "Connecting";
|
||||
break;
|
||||
case 3:
|
||||
//- Socket state
|
||||
stateText = "Connected";
|
||||
break;
|
||||
case 4:
|
||||
//- Socket state
|
||||
stateText = "Bound";
|
||||
break;
|
||||
case 5:
|
||||
//- Socket state
|
||||
stateText = "Closing";
|
||||
break;
|
||||
case 6:
|
||||
//- Socket state
|
||||
stateText = "Listening";
|
||||
break;
|
||||
}
|
||||
//- Socket state: "state no (state description)"
|
||||
qsTr("%1 (%2)").arg(ApiClient.websocket.state).arg(stateText)
|
||||
}
|
||||
}
|
||||
|
||||
SectionHeader {
|
||||
text: qsTr("Device profile")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue