Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8327fc5c9 | ||
|
|
9ffe03f0df | ||
|
|
37e99d7fed | ||
|
|
9b0e3762ac | ||
|
|
48f93e3480 | ||
|
|
2e9c093cdc | ||
|
|
60593dc855 | ||
|
|
0edde43720 | ||
|
|
0f6938a91d |
@@ -31,6 +31,7 @@ namespace Jellyfin.Plugin.MediaBarEnhanced.Configuration
|
|||||||
public bool AlwaysShowArrows { get; set; } = false;
|
public bool AlwaysShowArrows { get; set; } = false;
|
||||||
public string CustomMediaIds { get; set; } = "";
|
public string CustomMediaIds { get; set; } = "";
|
||||||
public bool EnableCustomMediaIds { get; set; } = true;
|
public bool EnableCustomMediaIds { get; set; } = true;
|
||||||
|
public string PreferredVideoQuality { get; set; } = "Auto";
|
||||||
public bool EnableSeasonalContent { get; set; } = false;
|
public bool EnableSeasonalContent { get; set; } = false;
|
||||||
public bool IsEnabled { get; set; } = true;
|
public bool IsEnabled { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,6 +156,18 @@
|
|||||||
</label>
|
</label>
|
||||||
<div class="fieldDescription">Skip intro/outro segments in YouTube trailers.</div>
|
<div class="fieldDescription">Skip intro/outro segments in YouTube trailers.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="selectContainer">
|
||||||
|
<label class="selectLabel" for="PreferredVideoQuality">Preferred YouTube Quality</label>
|
||||||
|
<select is="emby-select" id="PreferredVideoQuality" name="PreferredVideoQuality"
|
||||||
|
class="emby-select-withcolor emby-select">
|
||||||
|
<option value="Auto">Auto (Smart)</option>
|
||||||
|
<option value="Maximum">Maximum (4K+)</option>
|
||||||
|
<option value="1080p">1080p</option>
|
||||||
|
<option value="720p">720p</option>
|
||||||
|
</select>
|
||||||
|
<div class="fieldDescription">"Auto" selects Maximum if screen width > 1920px, otherwise
|
||||||
|
1080p.</div>
|
||||||
|
</div>
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label>
|
<label>
|
||||||
<input is="emby-checkbox" type="checkbox" id="StartMuted" name="StartMuted" />
|
<input is="emby-checkbox" type="checkbox" id="StartMuted" name="StartMuted" />
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
||||||
<Title>Jellyfin Media Bar Enhanced Plugin</Title>
|
<Title>Jellyfin Media Bar Enhanced Plugin</Title>
|
||||||
<Authors>CodeDevMLH</Authors>
|
<Authors>CodeDevMLH</Authors>
|
||||||
<Version>1.1.0.0</Version>
|
<Version>1.2.0.0</Version>
|
||||||
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced</RepositoryUrl>
|
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const CONFIG = {
|
|||||||
fullWidthVideo: true,
|
fullWidthVideo: true,
|
||||||
enableMobileVideo: false,
|
enableMobileVideo: false,
|
||||||
showTrailerButton: true,
|
showTrailerButton: true,
|
||||||
|
preferredVideoQuality: "Auto",
|
||||||
enableKeyboardControls: true,
|
enableKeyboardControls: true,
|
||||||
alwaysShowArrows: false,
|
alwaysShowArrows: false,
|
||||||
enableCustomMediaIds: true,
|
enableCustomMediaIds: true,
|
||||||
@@ -1259,11 +1260,13 @@ const VisibilityObserver = {
|
|||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
if (STATE.slideshow.slideInterval && !STATE.slideshow.isPaused) {
|
if (STATE.slideshow.slideInterval && !STATE.slideshow.isPaused) {
|
||||||
STATE.slideshow.slideInterval.start();
|
STATE.slideshow.slideInterval.start();
|
||||||
|
SlideshowManager.resumeActivePlayback();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (STATE.slideshow.slideInterval) {
|
if (STATE.slideshow.slideInterval) {
|
||||||
STATE.slideshow.slideInterval.stop();
|
STATE.slideshow.slideInterval.stop();
|
||||||
}
|
}
|
||||||
|
SlideshowManager.stopAllPlayback();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1415,6 +1418,21 @@ const SlideCreator = {
|
|||||||
loop: 0
|
loop: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Determine video quality
|
||||||
|
let quality = 'hd1080';
|
||||||
|
if (CONFIG.preferredVideoQuality === 'Maximum') {
|
||||||
|
quality = 'highres';
|
||||||
|
} else if (CONFIG.preferredVideoQuality === '720p') {
|
||||||
|
quality = 'hd720';
|
||||||
|
} else if (CONFIG.preferredVideoQuality === '1080p') {
|
||||||
|
quality = 'hd1080';
|
||||||
|
} else { // Auto or fallback
|
||||||
|
// If screen is wider than 1920, prefer highres, otherwise 1080p
|
||||||
|
quality = window.screen.width > 1920 ? 'highres' : 'hd1080';
|
||||||
|
}
|
||||||
|
|
||||||
|
playerVars.suggestedQuality = quality;
|
||||||
|
|
||||||
// Apply SponsorBlock start/end times
|
// Apply SponsorBlock start/end times
|
||||||
if (segments.intro) {
|
if (segments.intro) {
|
||||||
playerVars.start = Math.ceil(segments.intro[1]);
|
playerVars.start = Math.ceil(segments.intro[1]);
|
||||||
@@ -1444,6 +1462,10 @@ const SlideCreator = {
|
|||||||
event.target.setVolume(40);
|
event.target.setVolume(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof event.target.setPlaybackQuality === 'function') {
|
||||||
|
event.target.setPlaybackQuality(quality);
|
||||||
|
}
|
||||||
|
|
||||||
// Only play if this is the active slide
|
// Only play if this is the active slide
|
||||||
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
const slide = document.querySelector(`.slide[data-item-id="${itemId}"]`);
|
||||||
if (slide && slide.classList.contains('active')) {
|
if (slide && slide.classList.contains('active')) {
|
||||||
@@ -1492,6 +1514,7 @@ const SlideCreator = {
|
|||||||
className: "backdrop video-backdrop",
|
className: "backdrop video-backdrop",
|
||||||
src: trailerUrl,
|
src: trailerUrl,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
|
preload: "auto",
|
||||||
loop: false,
|
loop: false,
|
||||||
style: "object-fit: cover; width: 100%; height: 100%; pointer-events: none;"
|
style: "object-fit: cover; width: 100%; height: 100%; pointer-events: none;"
|
||||||
};
|
};
|
||||||
@@ -2317,6 +2340,65 @@ const SlideshowManager = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops all video playback (YouTube and HTML5)
|
||||||
|
* Used when navigating away from the home screen
|
||||||
|
*/
|
||||||
|
stopAllPlayback() {
|
||||||
|
// 1. Pause all YouTube players
|
||||||
|
if (STATE.slideshow.videoPlayers) {
|
||||||
|
Object.values(STATE.slideshow.videoPlayers).forEach(player => {
|
||||||
|
try {
|
||||||
|
if (player && typeof player.pauseVideo === 'function') {
|
||||||
|
player.pauseVideo();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Error pausing YouTube player:", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Pause all HTML5 videos
|
||||||
|
const container = document.getElementById("slides-container");
|
||||||
|
if (container) {
|
||||||
|
container.querySelectorAll('video').forEach(video => {
|
||||||
|
try {
|
||||||
|
video.pause();
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Error pausing HTML5 video:", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes playback for the active slide if not globally paused
|
||||||
|
*/
|
||||||
|
resumeActivePlayback() {
|
||||||
|
if (STATE.slideshow.isPaused) return;
|
||||||
|
|
||||||
|
const currentItemId = STATE.slideshow.itemIds[STATE.slideshow.currentSlideIndex];
|
||||||
|
if (!currentItemId) return;
|
||||||
|
|
||||||
|
const currentSlide = document.querySelector(`.slide[data-item-id="${currentItemId}"]`);
|
||||||
|
if (!currentSlide) return;
|
||||||
|
|
||||||
|
// 1. Try YouTube Player
|
||||||
|
const ytPlayer = STATE.slideshow.videoPlayers[currentItemId];
|
||||||
|
if (ytPlayer && typeof ytPlayer.playVideo === 'function') {
|
||||||
|
ytPlayer.playVideo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Try HTML5 Video
|
||||||
|
const html5Video = currentSlide.querySelector('video');
|
||||||
|
if (html5Video) {
|
||||||
|
if (STATE.slideshow.isMuted) {
|
||||||
|
html5Video.muted = true;
|
||||||
|
}
|
||||||
|
html5Video.play().catch(e => console.warn("Error resuming HTML5 video:", e));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes touch events for swiping
|
* Initializes touch events for swiping
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,30 @@
|
|||||||
"category": "General",
|
"category": "General",
|
||||||
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png",
|
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png",
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"version": "1.2.0.0",
|
||||||
|
"changelog": "- Add video quality preference setting (Auto / 1080p / Highres)\n- Set preferred video quality on YouTube player based on setting",
|
||||||
|
"targetAbi": "10.11.0.0",
|
||||||
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.2.0.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
|
"checksum": "2f1628d864b35cb710431974a8b85bee",
|
||||||
|
"timestamp": "2026-01-08T22:16:05Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "1.1.2.0",
|
||||||
|
"changelog": "- Add method to resume video playback when slideshow is active",
|
||||||
|
"targetAbi": "10.11.0.0",
|
||||||
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.1.2.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
|
"checksum": "a0e8ff5e59b22a1bdedc916cd5e1c16a",
|
||||||
|
"timestamp": "2026-01-08T15:26:55Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "1.1.1.0",
|
||||||
|
"changelog": "- Add method to pause all video playback when navigating away from home screen",
|
||||||
|
"targetAbi": "10.11.0.0",
|
||||||
|
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.1.1.0/Jellyfin.Plugin.MediaBarEnhanced.zip",
|
||||||
|
"checksum": "09da95fc561b11191d23a5cfa30ea731",
|
||||||
|
"timestamp": "2026-01-08T14:54:57Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.1.0.0",
|
"version": "1.1.0.0",
|
||||||
"changelog": "- 'custom media IDs' setting is now enabled by default (no input --> random selection)\n- improve GUID handling in slideshow manager to handle seperator and description",
|
"changelog": "- 'custom media IDs' setting is now enabled by default (no input --> random selection)\n- improve GUID handling in slideshow manager to handle seperator and description",
|
||||||
|
|||||||
Reference in New Issue
Block a user